func TestErrors(t *testing.T) { oc, _, _ := NewErrorClients(errors.NewNotFound(deployapi.Resource("DeploymentConfigList"), "")) _, err := oc.DeploymentConfigs("test").List(kapi.ListOptions{}) if !errors.IsNotFound(err) { t.Fatalf("unexpected error: %v", err) } oc, _, _ = NewErrorClients(errors.NewForbidden(deployapi.Resource("DeploymentConfigList"), "", nil)) _, err = oc.DeploymentConfigs("test").List(kapi.ListOptions{}) if !errors.IsForbidden(err) { t.Fatalf("unexpected error: %v", err) } }
// NewREST returns a deploymentConfigREST containing the REST storage for DeploymentConfig objects, // a statusREST containing the REST storage for changing the status of a DeploymentConfig, // and a scaleREST containing the REST storage for the Scale subresources of DeploymentConfigs. func NewREST(optsGetter restoptions.Getter) (*REST, *StatusREST, *ScaleREST, error) { store := ®istry.Store{ NewFunc: func() runtime.Object { return &api.DeploymentConfig{} }, NewListFunc: func() runtime.Object { return &api.DeploymentConfigList{} }, QualifiedResource: api.Resource("deploymentconfigs"), ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*api.DeploymentConfig).Name, nil }, PredicateFunc: func(label labels.Selector, field fields.Selector) storage.SelectionPredicate { return deployconfig.Matcher(label, field) }, CreateStrategy: deployconfig.Strategy, UpdateStrategy: deployconfig.Strategy, DeleteStrategy: deployconfig.Strategy, ReturnDeletedObject: false, } if err := restoptions.ApplyOptions(optsGetter, store, true, storage.NoTriggerPublisher); err != nil { return nil, nil, nil, err } deploymentConfigREST := &REST{store} statusStore := *store statusStore.UpdateStrategy = deployconfig.StatusStrategy statusREST := &StatusREST{store: &statusStore} scaleREST := &ScaleREST{registry: deployconfig.NewRegistry(deploymentConfigREST)} return deploymentConfigREST, statusREST, scaleREST, nil }
func AddHPAScaleRefEdges(g osgraph.Graph) { for _, node := range g.NodesByKind(kubegraph.HorizontalPodAutoscalerNodeKind) { hpaNode := node.(*kubegraph.HorizontalPodAutoscalerNode) syntheticMeta := kapi.ObjectMeta{ Name: hpaNode.HorizontalPodAutoscaler.Spec.ScaleRef.Name, Namespace: hpaNode.HorizontalPodAutoscaler.Namespace, } var groupVersionResource unversioned.GroupVersionResource resource := strings.ToLower(hpaNode.HorizontalPodAutoscaler.Spec.ScaleRef.Kind) if groupVersion, err := unversioned.ParseGroupVersion(hpaNode.HorizontalPodAutoscaler.Spec.ScaleRef.APIVersion); err == nil { groupVersionResource = groupVersion.WithResource(resource) } else { groupVersionResource = unversioned.GroupVersionResource{Resource: resource} } groupVersionResource, err := registered.RESTMapper().ResourceFor(groupVersionResource) if err != nil { continue } var syntheticNode graph.Node switch groupVersionResource.GroupResource() { case kapi.Resource("replicationcontrollers"): syntheticNode = kubegraph.FindOrCreateSyntheticReplicationControllerNode(g, &kapi.ReplicationController{ObjectMeta: syntheticMeta}) case deployapi.Resource("deploymentconfigs"): syntheticNode = deploygraph.FindOrCreateSyntheticDeploymentConfigNode(g, &deployapi.DeploymentConfig{ObjectMeta: syntheticMeta}) default: continue } g.AddEdge(hpaNode, syntheticNode, ScalingEdgeKind) } }
func TestCreateMissingDeploymentConfigDepr(t *testing.T) { rest := DeprecatedREST{ generator: Client{ GRFn: func(from, to *deployapi.DeploymentConfig, spec *deployapi.DeploymentConfigRollbackSpec) (*deployapi.DeploymentConfig, error) { t.Fatal("unexpected call to generator") return nil, errors.New("something terrible happened") }, RCFn: func(ctx kapi.Context, name string) (*kapi.ReplicationController, error) { deployment, _ := deployutil.MakeDeployment(deploytest.OkDeploymentConfig(1), kapi.Codecs.LegacyCodec(deployapi.SchemeGroupVersion)) return deployment, nil }, DCFn: func(ctx kapi.Context, name string) (*deployapi.DeploymentConfig, error) { return nil, kerrors.NewNotFound(deployapi.Resource("deploymentConfig"), name) }, }, codec: kapi.Codecs.LegacyCodec(deployapi.SchemeGroupVersion), } obj, err := rest.Create(kapi.NewDefaultContext(), &deployapi.DeploymentConfigRollback{ Spec: deployapi.DeploymentConfigRollbackSpec{ From: kapi.ObjectReference{ Name: "deployment", Namespace: kapi.NamespaceDefault, }, }, }) if err == nil { t.Errorf("Expected an error") } if obj != nil { t.Error("Unexpected result obj") } }
func printDeploymentConfigSpec(kc kclient.Interface, dc deployapi.DeploymentConfig, w *tabwriter.Writer) error { spec := dc.Spec // Selector formatString(w, "Selector", formatLabels(spec.Selector)) // Replicas test := "" if spec.Test { test = " (test, will be scaled down between deployments)" } formatString(w, "Replicas", fmt.Sprintf("%d%s", spec.Replicas, test)) // Autoscaling info printAutoscalingInfo(deployapi.Resource("DeploymentConfig"), dc.Namespace, dc.Name, kc, w) // Triggers printTriggers(spec.Triggers, w) // Strategy formatString(w, "Strategy", spec.Strategy.Type) printStrategy(spec.Strategy, " ", w) if dc.Spec.MinReadySeconds > 0 { formatString(w, "MinReadySeconds", fmt.Sprintf("%d", spec.MinReadySeconds)) } // Pod template fmt.Fprintf(w, "Template:\n") kctl.DescribePodTemplate(spec.Template, w) return nil }
func TestCreateMissingDeploymentConfig(t *testing.T) { oc := &testclient.Fake{} oc.AddReactor("get", "deploymentconfigs", func(action ktestclient.Action) (handled bool, ret runtime.Object, err error) { dc := deploytest.OkDeploymentConfig(2) return true, nil, kerrors.NewNotFound(deployapi.Resource("deploymentConfig"), dc.Name) }) kc := &ktestclient.Fake{} kc.AddReactor("get", "replicationcontrollers", func(action ktestclient.Action) (handled bool, ret runtime.Object, err error) { deployment, _ := deployutil.MakeDeployment(deploytest.OkDeploymentConfig(1), codec) return true, deployment, nil }) obj, err := NewREST(oc, kc, codec).Create(kapi.NewDefaultContext(), &deployapi.DeploymentConfigRollback{ Name: "config", Spec: deployapi.DeploymentConfigRollbackSpec{ Revision: 1, }, }) if err == nil { t.Errorf("Expected an error") } if obj != nil { t.Error("Unexpected result obj") } }
// NewStorage returns a DeploymentConfigStorage containing the REST storage for // DeploymentConfig objects and their Scale subresources. func NewREST(s storage.Interface, rcNamespacer kclient.ReplicationControllersNamespacer) (*REST, *ScaleREST) { prefix := "/deploymentconfigs" store := &etcdgeneric.Etcd{ NewFunc: func() runtime.Object { return &api.DeploymentConfig{} }, NewListFunc: func() runtime.Object { return &api.DeploymentConfigList{} }, QualifiedResource: api.Resource("deploymentconfigs"), KeyRootFunc: func(ctx kapi.Context) string { return etcdgeneric.NamespaceKeyRootFunc(ctx, prefix) }, KeyFunc: func(ctx kapi.Context, id string) (string, error) { return etcdgeneric.NamespaceKeyFunc(ctx, prefix, id) }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*api.DeploymentConfig).Name, nil }, PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher { return deployconfig.Matcher(label, field) }, CreateStrategy: deployconfig.Strategy, UpdateStrategy: deployconfig.Strategy, DeleteStrategy: deployconfig.Strategy, ReturnDeletedObject: false, Storage: s, } deploymentConfigREST := &REST{store} scaleREST := &ScaleREST{ registry: deployconfig.NewRegistry(deploymentConfigREST), rcNamespacer: rcNamespacer, } return deploymentConfigREST, scaleREST }
func TestErrors(t *testing.T) { o := testclient.NewObjects(kapi.Scheme, kapi.Codecs.UniversalDecoder()) o.Add(&kapi.List{ Items: []runtime.Object{ &(errors.NewNotFound(deployapi.Resource("DeploymentConfigList"), "").ErrStatus), &(errors.NewForbidden(deployapi.Resource("DeploymentConfigList"), "", nil).ErrStatus), }, }) oc, _ := NewFixtureClients(o) _, err := oc.DeploymentConfigs("test").List(kapi.ListOptions{}) if !errors.IsNotFound(err) { t.Fatalf("unexpected error: %v", err) } t.Logf("error: %#v", err.(*errors.StatusError).Status()) _, err = oc.DeploymentConfigs("test").List(kapi.ListOptions{}) if !errors.IsForbidden(err) { t.Fatalf("unexpected error: %v", err) } }
// Get retrieves the DeploymentConfig from the indexer for a given namespace and name. func (s deploymentConfigNamespaceLister) Get(name string) (*api.DeploymentConfig, error) { obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) if err != nil { return nil, err } if !exists { return nil, errors.NewNotFound(api.Resource("deploymentconfig"), name) } return obj.(*api.DeploymentConfig), nil }
// GetConfigForPod returns the managing deployment config for the provided pod. func (s *StoreToDeploymentConfigLister) GetConfigForPod(pod *kapi.Pod) (*deployapi.DeploymentConfig, error) { dcName := deployutil.DeploymentConfigNameFor(pod) obj, exists, err := s.Indexer.GetByKey(pod.Namespace + "/" + dcName) if err != nil { return nil, err } if !exists { return nil, kapierrors.NewNotFound(deployapi.Resource("deploymentconfig"), dcName) } return obj.(*deployapi.DeploymentConfig), nil }
func TestGenerate_fromMissingDeploymentConfig(t *testing.T) { generator := &DeploymentConfigGenerator{ Client: Client{ DCFn: func(ctx kapi.Context, id string) (*deployapi.DeploymentConfig, error) { return nil, kerrors.NewNotFound(deployapi.Resource("DeploymentConfig"), id) }, }, } config, err := generator.Generate(kapi.NewDefaultContext(), "1234") if config != nil { t.Fatalf("Unexpected DeploymentConfig generated: %#v", config) } if err == nil { t.Fatalf("Expected an error") } }
func TestGenerate_reportsNotFoundErrorWhenMissingDeploymentConfig(t *testing.T) { generator := &DeploymentConfigGenerator{ Client: Client{ DCFn: func(ctx kapi.Context, name string) (*deployapi.DeploymentConfig, error) { return nil, kerrors.NewNotFound(deployapi.Resource("DeploymentConfig"), name) }, ISFn: func(ctx kapi.Context, name string) (*imageapi.ImageStream, error) { return nil, kerrors.NewNotFound(imageapi.Resource("ImageStream"), name) }, }, } _, err := generator.Generate(kapi.NewDefaultContext(), "deploy1") if err == nil || !kerrors.IsNotFound(err) { t.Fatalf("Unexpected error type: %v", err) } if !strings.Contains(err.Error(), "DeploymentConfig \"deploy1\" not found") { t.Errorf("unexpected error message: %v", err) } }
// NewStorage returns a DeploymentConfigStorage containing the REST storage for // DeploymentConfig objects and their Scale subresources. func NewREST(optsGetter restoptions.Getter, rcNamespacer kclient.ReplicationControllersNamespacer) (*REST, *StatusREST, *ScaleREST, error) { prefix := "/deploymentconfigs" store := ®istry.Store{ NewFunc: func() runtime.Object { return &api.DeploymentConfig{} }, NewListFunc: func() runtime.Object { return &api.DeploymentConfigList{} }, QualifiedResource: api.Resource("deploymentconfigs"), KeyRootFunc: func(ctx kapi.Context) string { return registry.NamespaceKeyRootFunc(ctx, prefix) }, KeyFunc: func(ctx kapi.Context, id string) (string, error) { return registry.NamespaceKeyFunc(ctx, prefix, id) }, ObjectNameFunc: func(obj runtime.Object) (string, error) { return obj.(*api.DeploymentConfig).Name, nil }, PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher { return deployconfig.Matcher(label, field) }, CreateStrategy: deployconfig.Strategy, UpdateStrategy: deployconfig.Strategy, DeleteStrategy: deployconfig.Strategy, ReturnDeletedObject: false, } if err := restoptions.ApplyOptions(optsGetter, store, prefix); err != nil { return nil, nil, nil, err } deploymentConfigREST := &REST{store} statusStore := *store statusStore.UpdateStrategy = deployconfig.StatusStrategy statusREST := &StatusREST{store: &statusStore} scaleREST := &ScaleREST{ registry: deployconfig.NewRegistry(deploymentConfigREST), rcNamespacer: rcNamespacer, } return deploymentConfigREST, statusREST, scaleREST, nil }
// Get returns a streamer resource with the contents of the deployment log func (r *REST) Get(ctx kapi.Context, name string, opts runtime.Object) (runtime.Object, error) { // Ensure we have a namespace in the context namespace, ok := kapi.NamespaceFrom(ctx) if !ok { return nil, errors.NewBadRequest("namespace parameter required.") } // Validate DeploymentLogOptions deployLogOpts, ok := opts.(*deployapi.DeploymentLogOptions) if !ok { return nil, errors.NewBadRequest("did not get an expected options.") } if errs := validation.ValidateDeploymentLogOptions(deployLogOpts); len(errs) > 0 { return nil, errors.NewInvalid(deployapi.Kind("DeploymentLogOptions"), "", errs) } // Fetch deploymentConfig and check latest version; if 0, there are no deployments // for this config config, err := r.dn.DeploymentConfigs(namespace).Get(name) if err != nil { return nil, errors.NewNotFound(deployapi.Resource("deploymentconfig"), name) } desiredVersion := config.Status.LatestVersion if desiredVersion == 0 { return nil, errors.NewBadRequest(fmt.Sprintf("no deployment exists for deploymentConfig %q", config.Name)) } // Support retrieving logs for older deployments switch { case deployLogOpts.Version == nil: // Latest or previous if deployLogOpts.Previous { desiredVersion-- if desiredVersion < 1 { return nil, errors.NewBadRequest(fmt.Sprintf("no previous deployment exists for deploymentConfig %q", config.Name)) } } case *deployLogOpts.Version <= 0 || *deployLogOpts.Version > config.Status.LatestVersion: // Invalid version return nil, errors.NewBadRequest(fmt.Sprintf("invalid version for deploymentConfig %q: %d", config.Name, *deployLogOpts.Version)) default: desiredVersion = *deployLogOpts.Version } // Get desired deployment targetName := deployutil.DeploymentNameForConfigVersion(config.Name, desiredVersion) target, err := r.waitForExistingDeployment(namespace, targetName) if err != nil { return nil, err } podName := deployutil.DeployerPodNameForDeployment(target.Name) // Check for deployment status; if it is new or pending, we will wait for it. If it is complete, // the deployment completed successfully and the deployer pod will be deleted so we will return a // success message. If it is running or failed, retrieve the log from the deployer pod. status := deployutil.DeploymentStatusFor(target) switch status { case deployapi.DeploymentStatusNew, deployapi.DeploymentStatusPending: if deployLogOpts.NoWait { glog.V(4).Infof("Deployment %s is in %s state. No logs to retrieve yet.", deployutil.LabelForDeployment(target), status) return &genericrest.LocationStreamer{}, nil } glog.V(4).Infof("Deployment %s is in %s state, waiting for it to start...", deployutil.LabelForDeployment(target), status) if err := deployutil.WaitForRunningDeployerPod(r.pn, target, r.timeout); err != nil { return nil, errors.NewBadRequest(fmt.Sprintf("failed to run deployer pod %s: %v", podName, err)) } latest, ok, err := registry.WaitForRunningDeployment(r.rn, target, r.timeout) if err != nil { return nil, errors.NewBadRequest(fmt.Sprintf("unable to wait for deployment %s to run: %v", deployutil.LabelForDeployment(target), err)) } if !ok { return nil, errors.NewServerTimeout(kapi.Resource("ReplicationController"), "get", 2) } if deployutil.DeploymentStatusFor(latest) == deployapi.DeploymentStatusComplete { podName, err = r.returnApplicationPodName(target) if err != nil { return nil, err } } case deployapi.DeploymentStatusComplete: podName, err = r.returnApplicationPodName(target) if err != nil { return nil, err } } logOpts := deployapi.DeploymentToPodLogOptions(deployLogOpts) location, transport, err := pod.LogLocation(&podGetter{r.pn}, r.connInfo, ctx, podName, logOpts) if err != nil { return nil, errors.NewBadRequest(err.Error()) } return &genericrest.LocationStreamer{ Location: location, Transport: transport, ContentType: "text/plain", Flush: deployLogOpts.Follow, ResponseChecker: genericrest.NewGenericHttpResponseChecker(kapi.Resource("pod"), podName), }, nil }
func (f *Factory) PodForResource(resource string, timeout time.Duration) (string, error) { sortBy := func(pods []*api.Pod) sort.Interface { return sort.Reverse(controller.ActivePods(pods)) } namespace, _, err := f.DefaultNamespace() if err != nil { return "", err } mapper, _ := f.Object(false) resourceType, name, err := util.ResolveResource(api.Resource("pods"), resource, mapper) if err != nil { return "", err } switch resourceType { case api.Resource("pods"): return name, nil case api.Resource("replicationcontrollers"): kc, err := f.Client() if err != nil { return "", err } rc, err := kc.ReplicationControllers(namespace).Get(name) if err != nil { return "", err } selector := labels.SelectorFromSet(rc.Spec.Selector) pod, _, err := cmdutil.GetFirstPod(kc, namespace, selector, timeout, sortBy) if err != nil { return "", err } return pod.Name, nil case deployapi.Resource("deploymentconfigs"): oc, kc, err := f.Clients() if err != nil { return "", err } dc, err := oc.DeploymentConfigs(namespace).Get(name) if err != nil { return "", err } selector := labels.SelectorFromSet(dc.Spec.Selector) pod, _, err := cmdutil.GetFirstPod(kc, namespace, selector, timeout, sortBy) if err != nil { return "", err } return pod.Name, nil case extensions.Resource("daemonsets"): kc, err := f.Client() if err != nil { return "", err } ds, err := kc.Extensions().DaemonSets(namespace).Get(name) if err != nil { return "", err } selector, err := unversioned.LabelSelectorAsSelector(ds.Spec.Selector) if err != nil { return "", err } pod, _, err := cmdutil.GetFirstPod(kc, namespace, selector, timeout, sortBy) if err != nil { return "", err } return pod.Name, nil case extensions.Resource("jobs"): kc, err := f.Client() if err != nil { return "", err } job, err := kc.Extensions().Jobs(namespace).Get(name) if err != nil { return "", err } return podNameForJob(job, kc, timeout, sortBy) case batch.Resource("jobs"): kc, err := f.Client() if err != nil { return "", err } job, err := kc.Batch().Jobs(namespace).Get(name) if err != nil { return "", err } return podNameForJob(job, kc, timeout, sortBy) default: return "", fmt.Errorf("remote shell for %s is not supported", resourceType) } }
// Create instantiates a deployment config func (r *REST) Create(ctx kapi.Context, obj runtime.Object) (runtime.Object, error) { req, ok := obj.(*deployapi.DeploymentRequest) if !ok { return nil, errors.NewInternalError(fmt.Errorf("wrong object passed for requesting a new rollout: %#v", obj)) } configObj, err := r.store.Get(ctx, req.Name) if err != nil { return nil, err } config := configObj.(*deployapi.DeploymentConfig) old := config if errs := validation.ValidateRequestForDeploymentConfig(req, config); len(errs) > 0 { return nil, errors.NewInvalid(deployapi.Kind("DeploymentRequest"), req.Name, errs) } // We need to process the deployment config before we can determine if it is possible to trigger // a deployment. if req.Latest { if err := processTriggers(config, r.isn, req.Force); err != nil { return nil, err } } canTrigger, causes, err := canTrigger(config, r.rn, r.decoder, req.Force) if err != nil { return nil, err } // If we cannot trigger then there is nothing to do here. if !canTrigger { return &unversioned.Status{ Message: fmt.Sprintf("deployment config %q cannot be instantiated", config.Name), Code: int32(204), }, nil } glog.V(4).Infof("New deployment for %q caused by %#v", config.Name, causes) config.Status.Details = new(deployapi.DeploymentDetails) config.Status.Details.Causes = causes switch causes[0].Type { case deployapi.DeploymentTriggerOnConfigChange: config.Status.Details.Message = "config change" case deployapi.DeploymentTriggerOnImageChange: config.Status.Details.Message = "image change" case deployapi.DeploymentTriggerManual: config.Status.Details.Message = "manual change" } config.Status.LatestVersion++ userInfo, _ := kapi.UserFrom(ctx) attrs := admission.NewAttributesRecord(config, old, deployapi.Kind("DeploymentConfig").WithVersion(""), config.Namespace, config.Name, deployapi.Resource("DeploymentConfig").WithVersion(""), "", admission.Update, userInfo) if err := r.admit.Admit(attrs); err != nil { return nil, err } updated, _, err := r.store.Update(ctx, config.Name, rest.DefaultUpdatedObjectInfo(config, kapi.Scheme)) return updated, err }
func TestClusterReaderCoverage(t *testing.T) { testutil.RequireEtcd(t) defer testutil.DumpEtcdOnFailure(t) _, clusterAdminKubeConfig, err := testserver.StartTestMasterAPI() if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } discoveryClient := client.NewDiscoveryClient(clusterAdminClient.RESTClient) // (map[string]*unversioned.APIResourceList, error) allResourceList, err := discoveryClient.ServerResources() if err != nil { t.Fatalf("unexpected error: %v", err) } allResources := map[unversioned.GroupResource]bool{} for _, resources := range allResourceList { version, err := unversioned.ParseGroupVersion(resources.GroupVersion) if err != nil { t.Fatalf("unexpected error: %v", err) } for _, resource := range resources.APIResources { allResources[version.WithResource(resource.Name).GroupResource()] = true } } escalatingResources := map[unversioned.GroupResource]bool{ oauthapi.Resource("oauthauthorizetokens"): true, oauthapi.Resource("oauthaccesstokens"): true, oauthapi.Resource("oauthclients"): true, imageapi.Resource("imagestreams/secrets"): true, kapi.Resource("secrets"): true, kapi.Resource("pods/exec"): true, kapi.Resource("pods/proxy"): true, kapi.Resource("pods/portforward"): true, kapi.Resource("nodes/proxy"): true, kapi.Resource("services/proxy"): true, } readerRole, err := clusterAdminClient.ClusterRoles().Get(bootstrappolicy.ClusterReaderRoleName) if err != nil { t.Fatalf("unexpected error: %v", err) } for _, rule := range readerRole.Rules { for _, group := range rule.APIGroups { for resource := range rule.Resources { gr := unversioned.GroupResource{Group: group, Resource: resource} if escalatingResources[gr] { t.Errorf("cluster-reader role has escalating resource %v. Check pkg/cmd/server/bootstrappolicy/policy.go.", gr) } delete(allResources, gr) } } } // remove escalating resources that cluster-reader should not have access to for resource := range escalatingResources { delete(allResources, resource) } // remove resources without read APIs nonreadingResources := []unversioned.GroupResource{ buildapi.Resource("buildconfigs/instantiatebinary"), buildapi.Resource("buildconfigs/instantiate"), buildapi.Resource("builds/clone"), deployapi.Resource("deploymentconfigrollbacks"), deployapi.Resource("generatedeploymentconfigs"), deployapi.Resource("deploymentconfigs/rollback"), imageapi.Resource("imagestreamimports"), imageapi.Resource("imagestreammappings"), extensionsapi.Resource("deployments/rollback"), kapi.Resource("pods/attach"), kapi.Resource("namespaces/finalize"), } for _, resource := range nonreadingResources { delete(allResources, resource) } // anything left in the map is missing from the permissions if len(allResources) > 0 { t.Errorf("cluster-reader role is missing %v. Check pkg/cmd/server/bootstrappolicy/policy.go.", allResources) } }
authorizer authorizer.Authorizer } // resourcesToCheck is a map of resources and corresponding kinds of things that // we want handled in this plugin // TODO: Include a function that will extract the PodSpec from the resource for // each type added here. var resourcesToCheck = map[unversioned.GroupResource]unversioned.GroupKind{ kapi.Resource("pods"): kapi.Kind("Pod"), kapi.Resource("podtemplates"): kapi.Kind("PodTemplate"), kapi.Resource("replicationcontrollers"): kapi.Kind("ReplicationController"), batch.Resource("jobs"): batch.Kind("Job"), extensions.Resource("deployments"): extensions.Kind("Deployment"), extensions.Resource("replicasets"): extensions.Kind("ReplicaSet"), extensions.Resource("jobs"): extensions.Kind("Job"), deployapi.Resource("deploymentconfigs"): deployapi.Kind("DeploymentConfig"), } // resourcesToIgnore is a list of resource kinds that contain a PodSpec that // we choose not to handle in this plugin var resourcesToIgnore = []unversioned.GroupKind{ extensions.Kind("DaemonSet"), } func shouldCheckResource(resource unversioned.GroupResource, kind unversioned.GroupKind) (bool, error) { expectedKind, shouldCheck := resourcesToCheck[resource] if !shouldCheck { return false, nil } if expectedKind != kind { return false, fmt.Errorf("Unexpected resource kind %v for resource %v", &kind, &resource)
func TestPodNodeConstraintsResources(t *testing.T) { ns := kapi.NamespaceDefault testconfigs := []struct { config *api.PodNodeConstraintsConfig userinfo user.Info reviewResponse *authorizationapi.SubjectAccessReviewResponse }{ { config: testConfig(), userinfo: serviceaccount.UserInfo("", "", ""), reviewResponse: reviewResponse(false, ""), }, } testresources := []struct { resource func(bool) runtime.Object kind unversioned.GroupKind groupresource unversioned.GroupResource prefix string }{ { resource: replicationController, kind: kapi.Kind("ReplicationController"), groupresource: kapi.Resource("replicationcontrollers"), prefix: "ReplicationController", }, { resource: deployment, kind: extensions.Kind("Deployment"), groupresource: extensions.Resource("deployments"), prefix: "Deployment", }, { resource: replicaSet, kind: extensions.Kind("ReplicaSet"), groupresource: extensions.Resource("replicasets"), prefix: "ReplicaSet", }, { resource: job, kind: extensions.Kind("Job"), groupresource: extensions.Resource("jobs"), prefix: "Job", }, { resource: job, kind: batch.Kind("Job"), groupresource: batch.Resource("jobs"), prefix: "Job", }, { resource: deploymentConfig, kind: deployapi.Kind("DeploymentConfig"), groupresource: deployapi.Resource("deploymentconfigs"), prefix: "DeploymentConfig", }, { resource: podTemplate, kind: deployapi.Kind("PodTemplate"), groupresource: deployapi.Resource("podtemplates"), prefix: "PodTemplate", }, { resource: podSecurityPolicySubjectReview, kind: securityapi.Kind("PodSecurityPolicySubjectReview"), groupresource: securityapi.Resource("podsecuritypolicysubjectreviews"), prefix: "PodSecurityPolicy", }, { resource: podSecurityPolicySelfSubjectReview, kind: securityapi.Kind("PodSecurityPolicySelfSubjectReview"), groupresource: securityapi.Resource("podsecuritypolicyselfsubjectreviews"), prefix: "PodSecurityPolicy", }, { resource: podSecurityPolicyReview, kind: securityapi.Kind("PodSecurityPolicyReview"), groupresource: securityapi.Resource("podsecuritypolicyreviews"), prefix: "PodSecurityPolicy", }, } testparams := []struct { nodeselector bool expectedErrorMsg string prefix string }{ { nodeselector: true, expectedErrorMsg: "node selection by label(s) [bogus] is prohibited by policy for your role", prefix: "with nodeSelector", }, { nodeselector: false, expectedErrorMsg: "", prefix: "without nodeSelector", }, } testops := []struct { operation admission.Operation }{ { operation: admission.Create, }, { operation: admission.Update, }, } for _, tc := range testconfigs { for _, tr := range testresources { for _, tp := range testparams { for _, top := range testops { var expectedError error errPrefix := fmt.Sprintf("%s; %s; %s", tr.prefix, tp.prefix, top.operation) prc := NewPodNodeConstraints(tc.config) prc.(oadmission.WantsAuthorizer).SetAuthorizer(fakeAuthorizer(t)) err := prc.(oadmission.Validator).Validate() if err != nil { checkAdmitError(t, err, expectedError, errPrefix) continue } attrs := admission.NewAttributesRecord(tr.resource(tp.nodeselector), nil, tr.kind.WithVersion("version"), ns, "test", tr.groupresource.WithVersion("version"), "", top.operation, tc.userinfo) if tp.expectedErrorMsg != "" { expectedError = admission.NewForbidden(attrs, fmt.Errorf(tp.expectedErrorMsg)) } err = prc.Admit(attrs) checkAdmitError(t, err, expectedError, errPrefix) } } } } }
// Complete calls the upstream Complete for the logs command and then resolves the // resource a user requested to view its logs and creates the appropriate logOptions // object for it. func (o *OpenShiftLogsOptions) Complete(f *clientcmd.Factory, out io.Writer, cmd *cobra.Command, args []string) error { if err := o.KubeLogOptions.Complete(f.Factory, out, cmd, args); err != nil { return err } namespace, _, err := f.DefaultNamespace() if err != nil { return err } podLogOptions := o.KubeLogOptions.Options.(*kapi.PodLogOptions) mapper, typer := f.Object() infos, err := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), kapi.Codecs.UniversalDecoder()). NamespaceParam(namespace).DefaultNamespace(). ResourceNames("pods", args...). SingleResourceType().RequireObject(false). Do().Infos() if err != nil { return err } if len(infos) != 1 { return errors.New("expected a resource") } version := kcmdutil.GetFlagInt64(cmd, "version") _, resource := meta.KindToResource(infos[0].Mapping.GroupVersionKind, false) // TODO: podLogOptions should be included in our own logOptions objects. switch resource.GroupResource() { case buildapi.Resource("build"), buildapi.Resource("buildconfig"): bopts := &buildapi.BuildLogOptions{ Follow: podLogOptions.Follow, Previous: podLogOptions.Previous, SinceSeconds: podLogOptions.SinceSeconds, SinceTime: podLogOptions.SinceTime, Timestamps: podLogOptions.Timestamps, TailLines: podLogOptions.TailLines, LimitBytes: podLogOptions.LimitBytes, } if version != 0 { bopts.Version = &version } o.Options = bopts case deployapi.Resource("deploymentconfig"): dopts := &deployapi.DeploymentLogOptions{ Follow: podLogOptions.Follow, Previous: podLogOptions.Previous, SinceSeconds: podLogOptions.SinceSeconds, SinceTime: podLogOptions.SinceTime, Timestamps: podLogOptions.Timestamps, TailLines: podLogOptions.TailLines, LimitBytes: podLogOptions.LimitBytes, } if version != 0 { dopts.Version = &version } o.Options = dopts default: o.Options = nil } return nil }