func waitForQuota(t *testing.T, quota *v1.ResourceQuota, clientset *clientset.Clientset) { w, err := clientset.Core().ResourceQuotas(quota.Namespace).Watch(v1.SingleObject(metav1.ObjectMeta{Name: quota.Name})) if err != nil { t.Fatalf("unexpected error: %v", err) } if _, err := clientset.Core().ResourceQuotas(quota.Namespace).Create(quota); err != nil { t.Fatalf("unexpected error: %v", err) } _, err = watch.Until(1*time.Minute, w, func(event watch.Event) (bool, error) { switch event.Type { case watch.Modified: default: return false, nil } switch cast := event.Object.(type) { case *v1.ResourceQuota: if len(cast.Status.Hard) > 0 { return true, nil } } return false, nil }) if err != nil { t.Fatalf("unexpected error: %v", err) } }
func runAppArmorTest(f *framework.Framework, shouldRun bool, profile string) v1.PodStatus { pod := createPodWithAppArmor(f, profile) if shouldRun { // The pod needs to start before it stops, so wait for the longer start timeout. framework.ExpectNoError(framework.WaitTimeoutForPodNoLongerRunningInNamespace( f.ClientSet, pod.Name, f.Namespace.Name, "", framework.PodStartTimeout)) } else { // Pod should remain in the pending state. Wait for the Reason to be set to "AppArmor". w, err := f.PodClient().Watch(v1.SingleObject(metav1.ObjectMeta{Name: pod.Name})) framework.ExpectNoError(err) _, err = watch.Until(framework.PodStartTimeout, w, func(e watch.Event) (bool, error) { switch e.Type { case watch.Deleted: return false, errors.NewNotFound(schema.GroupResource{Resource: "pods"}, pod.Name) } switch t := e.Object.(type) { case *v1.Pod: if t.Status.Reason == "AppArmor" { return true, nil } } return false, nil }) framework.ExpectNoError(err) } p, err := f.PodClient().Get(pod.Name, metav1.GetOptions{}) framework.ExpectNoError(err) return p.Status }
func scale(t *testing.T, namespace string, clientset *clientset.Clientset) { target := int32(100) rc := &v1.ReplicationController{ ObjectMeta: metav1.ObjectMeta{ Name: "foo", Namespace: namespace, }, Spec: v1.ReplicationControllerSpec{ Replicas: &target, Selector: map[string]string{"foo": "bar"}, Template: &v1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ Labels: map[string]string{ "foo": "bar", }, }, Spec: v1.PodSpec{ Containers: []v1.Container{ { Name: "container", Image: "busybox", }, }, }, }, }, } w, err := clientset.Core().ReplicationControllers(namespace).Watch(v1.SingleObject(metav1.ObjectMeta{Name: rc.Name})) if err != nil { t.Fatalf("unexpected error: %v", err) } if _, err := clientset.Core().ReplicationControllers(namespace).Create(rc); err != nil { t.Fatalf("unexpected error: %v", err) } _, err = watch.Until(3*time.Minute, w, func(event watch.Event) (bool, error) { switch event.Type { case watch.Modified: default: return false, nil } switch cast := event.Object.(type) { case *v1.ReplicationController: fmt.Printf("Found %v of %v replicas\n", int(cast.Status.Replicas), target) if cast.Status.Replicas == target { return true, nil } } return false, nil }) if err != nil { pods, _ := clientset.Core().Pods(namespace).List(v1.ListOptions{LabelSelector: labels.Everything().String(), FieldSelector: fields.Everything().String()}) t.Fatalf("unexpected error: %v, ended with %v pods", err, len(pods.Items)) } }
// Scale updates a ReplicationController to a new size, with optional precondition check (if preconditions is not nil), // optional retries (if retry is not nil), and then optionally waits for it's replica count to reach the new value // (if wait is not nil). func (scaler *ReplicationControllerScaler) Scale(namespace, name string, newSize uint, preconditions *ScalePrecondition, retry, waitForReplicas *RetryParams) error { if preconditions == nil { preconditions = &ScalePrecondition{-1, ""} } if retry == nil { // Make it try only once, immediately retry = &RetryParams{Interval: time.Millisecond, Timeout: time.Millisecond} } var updatedResourceVersion string cond := ScaleCondition(scaler, preconditions, namespace, name, newSize, &updatedResourceVersion) if err := wait.PollImmediate(retry.Interval, retry.Timeout, cond); err != nil { return err } if waitForReplicas != nil { checkRC := func(rc *api.ReplicationController) bool { if uint(rc.Spec.Replicas) != newSize { // the size is changed by other party. Don't need to wait for the new change to complete. return true } return rc.Status.ObservedGeneration >= rc.Generation && rc.Status.Replicas == rc.Spec.Replicas } // If number of replicas doesn't change, then the update may not event // be sent to underlying databse (we don't send no-op changes). // In such case, <updatedResourceVersion> will have value of the most // recent update (which may be far in the past) so we may get "too old // RV" error from watch or potentially no ReplicationController events // will be deliver, since it may already be in the expected state. // To protect from these two, we first issue Get() to ensure that we // are not already in the expected state. currentRC, err := scaler.c.ReplicationControllers(namespace).Get(name, metav1.GetOptions{}) if err != nil { return err } if !checkRC(currentRC) { watchOptions := api.ListOptions{ FieldSelector: fields.OneTermEqualSelector("metadata.name", name), ResourceVersion: updatedResourceVersion, } watcher, err := scaler.c.ReplicationControllers(namespace).Watch(watchOptions) if err != nil { return err } _, err = watch.Until(waitForReplicas.Timeout, watcher, func(event watch.Event) (bool, error) { if event.Type != watch.Added && event.Type != watch.Modified { return false, nil } return checkRC(event.Object.(*api.ReplicationController)), nil }) if err == wait.ErrWaitTimeout { return fmt.Errorf("timed out waiting for %q to be synced", name) } return err } } return nil }
func TestBootstrapping(t *testing.T) { superUser := "******" masterConfig := framework.NewIntegrationTestMasterConfig() masterConfig.GenericConfig.Authorizer = newRBACAuthorizer(masterConfig) masterConfig.GenericConfig.Authenticator = newFakeAuthenticator() _, s := framework.RunAMaster(masterConfig) defer s.Close() clientset := clientset.NewForConfigOrDie(&restclient.Config{BearerToken: superUser, Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: &api.Registry.GroupOrDie(api.GroupName).GroupVersion}}) watcher, err := clientset.Rbac().ClusterRoles().Watch(api.ListOptions{ResourceVersion: "0"}) if err != nil { t.Fatalf("unexpected error: %v", err) } _, err = watch.Until(30*time.Second, watcher, func(event watch.Event) (bool, error) { if event.Type != watch.Added { return false, nil } return true, nil }) if err != nil { t.Fatalf("unexpected error: %v", err) } clusterRoles, err := clientset.Rbac().ClusterRoles().List(api.ListOptions{}) if err != nil { t.Fatalf("unexpected error: %v", err) } if len(clusterRoles.Items) == 0 { t.Fatalf("missing cluster roles") } for _, clusterRole := range clusterRoles.Items { if clusterRole.Name == "cluster-admin" { return } } t.Errorf("missing cluster-admin: %v", clusterRoles) healthBytes, err := clientset.Discovery().RESTClient().Get().AbsPath("/healthz/poststarthooks/rbac/bootstrap-roles").DoRaw() if err != nil { t.Error(err) } t.Errorf("expected %v, got %v", "asdf", string(healthBytes)) }
// waitForPod watches the given pod until the exitCondition is true func waitForPod(podClient coreclient.PodsGetter, ns, name string, exitCondition watch.ConditionFunc) (*api.Pod, error) { w, err := podClient.Pods(ns).Watch(api.SingleObject(metav1.ObjectMeta{Name: name})) if err != nil { return nil, err } intr := interrupt.New(nil, w.Stop) var result *api.Pod err = intr.Run(func() error { ev, err := watch.Until(0, w, func(ev watch.Event) (bool, error) { return exitCondition(ev) }) result = ev.Object.(*api.Pod) return err }) return result, err }
// GetFirstPod returns a pod matching the namespace and label selector // and the number of all pods that match the label selector. func GetFirstPod(client coreclient.PodsGetter, namespace string, selector labels.Selector, timeout time.Duration, sortBy func([]*v1.Pod) sort.Interface) (*api.Pod, int, error) { options := api.ListOptions{LabelSelector: selector} podList, err := client.Pods(namespace).List(options) if err != nil { return nil, 0, err } pods := []*v1.Pod{} for i := range podList.Items { pod := podList.Items[i] externalPod := &v1.Pod{} v1.Convert_api_Pod_To_v1_Pod(&pod, externalPod, nil) pods = append(pods, externalPod) } if len(pods) > 0 { sort.Sort(sortBy(pods)) internalPod := &api.Pod{} v1.Convert_v1_Pod_To_api_Pod(pods[0], internalPod, nil) return internalPod, len(podList.Items), nil } // Watch until we observe a pod options.ResourceVersion = podList.ResourceVersion w, err := client.Pods(namespace).Watch(options) if err != nil { return nil, 0, err } defer w.Stop() condition := func(event watch.Event) (bool, error) { return event.Type == watch.Added || event.Type == watch.Modified, nil } event, err := watch.Until(timeout, w, condition) if err != nil { return nil, 0, err } pod, ok := event.Object.(*api.Pod) if !ok { return nil, 0, fmt.Errorf("%#v is not a pod event", event) } return pod, 1, nil }
// startMasterOrDie starts a kubernetes master and an httpserver to handle api requests func startMasterOrDie(masterConfig *master.Config, incomingServer *httptest.Server, masterReceiver MasterReceiver) (*master.Master, *httptest.Server) { var m *master.Master var s *httptest.Server if incomingServer != nil { s = incomingServer } else { s = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { m.GenericAPIServer.Handler.ServeHTTP(w, req) })) } if masterConfig == nil { masterConfig = NewMasterConfig() masterConfig.GenericConfig.EnableProfiling = true masterConfig.GenericConfig.EnableMetrics = true masterConfig.GenericConfig.OpenAPIConfig = genericapiserver.DefaultOpenAPIConfig(openapi.OpenAPIDefinitions) masterConfig.GenericConfig.OpenAPIConfig.Info = &spec.Info{ InfoProps: spec.InfoProps{ Title: "Kubernetes", Version: "unversioned", }, } masterConfig.GenericConfig.OpenAPIConfig.DefaultResponse = &spec.Response{ ResponseProps: spec.ResponseProps{ Description: "Default Response.", }, } masterConfig.GenericConfig.OpenAPIConfig.Definitions = openapi.OpenAPIDefinitions masterConfig.GenericConfig.SwaggerConfig = genericapiserver.DefaultSwaggerConfig() } // set the loopback client config if masterConfig.GenericConfig.LoopbackClientConfig == nil { masterConfig.GenericConfig.LoopbackClientConfig = &restclient.Config{QPS: 50, Burst: 100, ContentConfig: restclient.ContentConfig{NegotiatedSerializer: api.Codecs}} } masterConfig.GenericConfig.LoopbackClientConfig.Host = s.URL privilegedLoopbackToken := uuid.NewRandom().String() // wrap any available authorizer tokens := make(map[string]*user.DefaultInfo) tokens[privilegedLoopbackToken] = &user.DefaultInfo{ Name: user.APIServerUser, UID: uuid.NewRandom().String(), Groups: []string{user.SystemPrivilegedGroup}, } tokenAuthenticator := authenticator.NewAuthenticatorFromTokens(tokens) if masterConfig.GenericConfig.Authenticator == nil { masterConfig.GenericConfig.Authenticator = authenticatorunion.New(tokenAuthenticator, authauthenticator.RequestFunc(alwaysEmpty)) } else { masterConfig.GenericConfig.Authenticator = authenticatorunion.New(tokenAuthenticator, masterConfig.GenericConfig.Authenticator) } if masterConfig.GenericConfig.Authorizer != nil { tokenAuthorizer := authorizer.NewPrivilegedGroups(user.SystemPrivilegedGroup) masterConfig.GenericConfig.Authorizer = authorizerunion.New(tokenAuthorizer, masterConfig.GenericConfig.Authorizer) } else { masterConfig.GenericConfig.Authorizer = alwaysAllow{} } masterConfig.GenericConfig.LoopbackClientConfig.BearerToken = privilegedLoopbackToken m, err := masterConfig.Complete().New() if err != nil { glog.Fatalf("error in bringing up the master: %v", err) } if masterReceiver != nil { masterReceiver.SetMaster(m) } // TODO have this start method actually use the normal start sequence for the API server // this method never actually calls the `Run` method for the API server // fire the post hooks ourselves m.GenericAPIServer.PrepareRun() m.GenericAPIServer.RunPostStartHooks() cfg := *masterConfig.GenericConfig.LoopbackClientConfig cfg.ContentConfig.GroupVersion = &schema.GroupVersion{} privilegedClient, err := restclient.RESTClientFor(&cfg) if err != nil { glog.Fatal(err) } err = wait.PollImmediate(100*time.Millisecond, 30*time.Second, func() (bool, error) { result := privilegedClient.Get().AbsPath("/healthz").Do() status := 0 result.StatusCode(&status) if status == 200 { return true, nil } return false, nil }) if err != nil { glog.Fatal(err) } // wait for services to be ready if masterConfig.EnableCoreControllers { // TODO Once /healthz is updated for posthooks, we'll wait for good health coreClient := coreclient.NewForConfigOrDie(&cfg) svcWatch, err := coreClient.Services(v1.NamespaceDefault).Watch(v1.ListOptions{}) if err != nil { glog.Fatal(err) } _, err = watch.Until(30*time.Second, svcWatch, func(event watch.Event) (bool, error) { if event.Type != watch.Added { return false, nil } if event.Object.(*v1.Service).Name == "kubernetes" { return true, nil } return false, nil }) if err != nil { glog.Fatal(err) } } return m, s }
// TODO: check for watch expired error and retry watch from latest point? Same issue exists for Until. func ListWatchUntil(timeout time.Duration, lw ListerWatcher, conditions ...watch.ConditionFunc) (*watch.Event, error) { if len(conditions) == 0 { return nil, nil } list, err := lw.List(v1.ListOptions{}) if err != nil { return nil, err } initialItems, err := meta.ExtractList(list) if err != nil { return nil, err } // use the initial items as simulated "adds" var lastEvent *watch.Event currIndex := 0 passedConditions := 0 for _, condition := range conditions { // check the next condition against the previous event and short circuit waiting for the next watch if lastEvent != nil { done, err := condition(*lastEvent) if err != nil { return lastEvent, err } if done { passedConditions = passedConditions + 1 continue } } ConditionSucceeded: for currIndex < len(initialItems) { lastEvent = &watch.Event{Type: watch.Added, Object: initialItems[currIndex]} currIndex++ done, err := condition(*lastEvent) if err != nil { return lastEvent, err } if done { passedConditions = passedConditions + 1 break ConditionSucceeded } } } if passedConditions == len(conditions) { return lastEvent, nil } remainingConditions := conditions[passedConditions:] metaObj, err := meta.ListAccessor(list) if err != nil { return nil, err } currResourceVersion := metaObj.GetResourceVersion() watchInterface, err := lw.Watch(v1.ListOptions{ResourceVersion: currResourceVersion}) if err != nil { return nil, err } return watch.Until(timeout, watchInterface, remainingConditions...) }
{ Name: "run1", Image: "gcr.io/google_containers/busybox:1.24", Command: []string{"/bin/true"}, }, }, }, } if err := podutil.SetInitContainersAnnotations(pod); err != nil { Expect(err).To(BeNil()) } startedPod := podClient.Create(pod) w, err := podClient.Watch(v1.SingleObject(startedPod.ObjectMeta)) Expect(err).NotTo(HaveOccurred(), "error watching a pod") wr := watch.NewRecorder(w) event, err := watch.Until(framework.PodStartTimeout, wr, conditions.PodCompleted) Expect(err).To(BeNil()) framework.CheckInvariants(wr.Events(), framework.ContainerInitInvariant) endPod := event.Object.(*v1.Pod) if err := podutil.SetInitContainersAndStatuses(endPod); err != nil { Expect(err).To(BeNil()) } Expect(endPod.Status.Phase).To(Equal(v1.PodSucceeded)) _, init := v1.GetPodCondition(&endPod.Status, v1.PodInitialized) Expect(init).NotTo(BeNil()) Expect(init.Status).To(Equal(v1.ConditionTrue)) Expect(len(endPod.Status.InitContainerStatuses)).To(Equal(2)) for _, status := range endPod.Status.InitContainerStatuses { Expect(status.Ready).To(BeTrue())
Name: expectedPod.Name, ResourceVersion: expectedPod.ResourceVersion, }, )) Expect(err).NotTo(HaveOccurred()) By("Verifying the 2nd pod is removed only when it becomes running and ready") sst.restoreProbe(ss, testProbe) _, err = watch.Until(statefulsetTimeout, watcher, func(event watch.Event) (bool, error) { pod := event.Object.(*v1.Pod) if event.Type == watch.Deleted && pod.Name == expectedPodName { return false, fmt.Errorf("Pod %v was deleted before enter running", pod.Name) } framework.Logf("Observed event %v for pod %v. Phase %v, Pod is ready %v", event.Type, pod.Name, pod.Status.Phase, v1.IsPodReady(pod)) if pod.Name != expectedPodName { return false, nil } if pod.Status.Phase == v1.PodRunning && v1.IsPodReady(pod) { return true, nil } return false, nil }) Expect(err).NotTo(HaveOccurred()) }) It("Scaling should happen in predictable order and halt if any stateful pod is unhealthy", func() { psLabels := klabels.Set(labels) By("Initializing watcher for selector " + psLabels.String()) watcher, err := f.ClientSet.Core().Pods(ns).Watch(v1.ListOptions{ LabelSelector: psLabels.AsSelector().String(),
// RunGet implements the generic Get command // TODO: convert all direct flag accessors to a struct and pass that instead of cmd func RunGet(f cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args []string, options *GetOptions) error { if len(options.Raw) > 0 { restClient, err := f.RESTClient() if err != nil { return err } stream, err := restClient.Get().RequestURI(options.Raw).Stream() if err != nil { return err } defer stream.Close() _, err = io.Copy(out, stream) if err != nil && err != io.EOF { return err } return nil } selector := cmdutil.GetFlagString(cmd, "selector") allNamespaces := cmdutil.GetFlagBool(cmd, "all-namespaces") showKind := cmdutil.GetFlagBool(cmd, "show-kind") mapper, typer, err := f.UnstructuredObject() if err != nil { return err } filterFuncs := f.DefaultResourceFilterFunc() filterOpts := f.DefaultResourceFilterOptions(cmd, allNamespaces) cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err } if allNamespaces { enforceNamespace = false } if len(args) == 0 && cmdutil.IsFilenameEmpty(options.Filenames) { fmt.Fprint(errOut, "You must specify the type of resource to get. ", valid_resources) fullCmdName := cmd.Parent().CommandPath() usageString := "Required resource not specified." if len(fullCmdName) > 0 && cmdutil.IsSiblingCommandExists(cmd, "explain") { usageString = fmt.Sprintf("%s\nUse \"%s explain <resource>\" for a detailed description of that resource (e.g. %[2]s explain pods).", usageString, fullCmdName) } return cmdutil.UsageError(cmd, usageString) } argsHasNames, err := resource.HasNames(args) if err != nil { return err } // always show resources when getting by name or filename, or if the output // is machine-consumable, or if multiple resource kinds were requested. if len(options.Filenames) > 0 || argsHasNames || cmdutil.OutputsRawFormat(cmd) { if !cmd.Flag("show-all").Changed { cmd.Flag("show-all").Value.Set("true") } } export := cmdutil.GetFlagBool(cmd, "export") // handle watch separately since we cannot watch multiple resource types isWatch, isWatchOnly := cmdutil.GetFlagBool(cmd, "watch"), cmdutil.GetFlagBool(cmd, "watch-only") if isWatch || isWatchOnly { r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme). NamespaceParam(cmdNamespace).DefaultNamespace().AllNamespaces(allNamespaces). FilenameParam(enforceNamespace, &options.FilenameOptions). SelectorParam(selector). ExportParam(export). ResourceTypeOrNameArgs(true, args...). SingleResourceType(). Latest(). Do() err := r.Err() if err != nil { return err } infos, err := r.Infos() if err != nil { return err } if len(infos) != 1 { return i18n.Errorf("watch is only supported on individual resources and resource collections - %d resources were found", len(infos)) } info := infos[0] mapping := info.ResourceMapping() printer, err := f.PrinterForMapping(cmd, mapping, allNamespaces) if err != nil { return err } obj, err := r.Object() if err != nil { return err } // watching from resourceVersion 0, starts the watch at ~now and // will return an initial watch event. Starting form ~now, rather // the rv of the object will insure that we start the watch from // inside the watch window, which the rv of the object might not be. rv := "0" isList := meta.IsListType(obj) if isList { // the resourceVersion of list objects is ~now but won't return // an initial watch event rv, err = mapping.MetadataAccessor.ResourceVersion(obj) if err != nil { return err } } // print the current object filteredResourceCount := 0 if !isWatchOnly { if err := printer.PrintObj(obj, out); err != nil { return fmt.Errorf("unable to output the provided object: %v", err) } filteredResourceCount++ cmdutil.PrintFilterCount(filteredResourceCount, mapping.Resource, filterOpts) } // print watched changes w, err := r.Watch(rv) if err != nil { return err } first := true filteredResourceCount = 0 intr := interrupt.New(nil, w.Stop) intr.Run(func() error { _, err := watch.Until(0, w, func(e watch.Event) (bool, error) { if !isList && first { // drop the initial watch event in the single resource case first = false return false, nil } err := printer.PrintObj(e.Object, out) if err != nil { return false, err } filteredResourceCount++ cmdutil.PrintFilterCount(filteredResourceCount, mapping.Resource, filterOpts) return false, nil }) return err }) return nil } r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.UnstructuredClientForMapping), unstructured.UnstructuredJSONScheme). NamespaceParam(cmdNamespace).DefaultNamespace().AllNamespaces(allNamespaces). FilenameParam(enforceNamespace, &options.FilenameOptions). SelectorParam(selector). ExportParam(export). ResourceTypeOrNameArgs(true, args...). ContinueOnError(). Latest(). Flatten(). Do() err = r.Err() if err != nil { return err } printer, generic, err := cmdutil.PrinterForCommand(cmd) if err != nil { return err } if generic { // we flattened the data from the builder, so we have individual items, but now we'd like to either: // 1. if there is more than one item, combine them all into a single list // 2. if there is a single item and that item is a list, leave it as its specific list // 3. if there is a single item and it is not a a list, leave it as a single item var errs []error singleItemImplied := false infos, err := r.IntoSingleItemImplied(&singleItemImplied).Infos() if err != nil { if singleItemImplied { return err } errs = append(errs, err) } if len(infos) == 0 && len(errs) == 0 { outputEmptyListWarning(errOut) } res := "" if len(infos) > 0 { res = infos[0].ResourceMapping().Resource } var obj runtime.Object if !singleItemImplied || len(infos) > 1 { // we have more than one item, so coerce all items into a list list := &unstructured.UnstructuredList{ Object: map[string]interface{}{ "kind": "List", "apiVersion": "v1", "metadata": map[string]interface{}{}, }, } for _, info := range infos { list.Items = append(list.Items, info.Object.(*unstructured.Unstructured)) } obj = list } else { obj = infos[0].Object } isList := meta.IsListType(obj) if isList { filteredResourceCount, items, err := cmdutil.FilterResourceList(obj, filterFuncs, filterOpts) if err != nil { return err } // take the filtered items and create a new list for display list := &unstructured.UnstructuredList{ Object: map[string]interface{}{ "kind": "List", "apiVersion": "v1", "metadata": map[string]interface{}{}, }, } if listMeta, err := meta.ListAccessor(obj); err == nil { list.Object["selfLink"] = listMeta.GetSelfLink() list.Object["resourceVersion"] = listMeta.GetResourceVersion() } for _, item := range items { list.Items = append(list.Items, item.(*unstructured.Unstructured)) } if err := printer.PrintObj(list, out); err != nil { errs = append(errs, err) } cmdutil.PrintFilterCount(filteredResourceCount, res, filterOpts) return utilerrors.Reduce(utilerrors.Flatten(utilerrors.NewAggregate(errs))) } filteredResourceCount := 0 if isFiltered, err := filterFuncs.Filter(obj, filterOpts); !isFiltered { if err != nil { glog.V(2).Infof("Unable to filter resource: %v", err) } else if err := printer.PrintObj(obj, out); err != nil { errs = append(errs, err) } } else if isFiltered { filteredResourceCount++ } cmdutil.PrintFilterCount(filteredResourceCount, res, filterOpts) return utilerrors.Reduce(utilerrors.Flatten(utilerrors.NewAggregate(errs))) } allErrs := []error{} errs := sets.NewString() infos, err := r.Infos() if err != nil { allErrs = append(allErrs, err) } if len(infos) == 0 && len(allErrs) == 0 { outputEmptyListWarning(errOut) } objs := make([]runtime.Object, len(infos)) for ix := range infos { objs[ix] = infos[ix].Object } sorting, err := cmd.Flags().GetString("sort-by") if err != nil { return err } var sorter *kubectl.RuntimeSort if len(sorting) > 0 && len(objs) > 1 { // TODO: questionable if sorter, err = kubectl.SortObjects(f.Decoder(true), objs, sorting); err != nil { return err } } // use the default printer for each object printer = nil var lastMapping *meta.RESTMapping w := kubectl.GetNewTabWriter(out) filteredResourceCount := 0 if resource.MultipleTypesRequested(args) || cmdutil.MustPrintWithKinds(objs, infos, sorter) { showKind = true } for ix := range objs { var mapping *meta.RESTMapping var original runtime.Object if sorter != nil { mapping = infos[sorter.OriginalPosition(ix)].Mapping original = infos[sorter.OriginalPosition(ix)].Object } else { mapping = infos[ix].Mapping original = infos[ix].Object } if printer == nil || lastMapping == nil || mapping == nil || mapping.Resource != lastMapping.Resource { if printer != nil { w.Flush() cmdutil.PrintFilterCount(filteredResourceCount, lastMapping.Resource, filterOpts) } printer, err = f.PrinterForMapping(cmd, mapping, allNamespaces) if err != nil { if !errs.Has(err.Error()) { errs.Insert(err.Error()) allErrs = append(allErrs, err) } continue } // add linebreak between resource groups (if there is more than one) // skip linebreak above first resource group noHeaders := cmdutil.GetFlagBool(cmd, "no-headers") if lastMapping != nil && !noHeaders { fmt.Fprintf(errOut, "%s\n", "") } lastMapping = mapping } // try to convert before apply filter func decodedObj, _ := kubectl.DecodeUnknownObject(original) // filter objects if filter has been defined for current object if isFiltered, err := filterFuncs.Filter(decodedObj, filterOpts); isFiltered { if err == nil { filteredResourceCount++ continue } if !errs.Has(err.Error()) { errs.Insert(err.Error()) allErrs = append(allErrs, err) } } if resourcePrinter, found := printer.(*kubectl.HumanReadablePrinter); found { resourceName := resourcePrinter.GetResourceKind() if mapping != nil { if resourceName == "" { resourceName = mapping.Resource } if alias, ok := kubectl.ResourceShortFormFor(mapping.Resource); ok { resourceName = alias } else if resourceName == "" { resourceName = "none" } } else { resourceName = "none" } if showKind { resourcePrinter.EnsurePrintWithKind(resourceName) } if err := printer.PrintObj(decodedObj, w); err != nil { if !errs.Has(err.Error()) { errs.Insert(err.Error()) allErrs = append(allErrs, err) } } continue } if err := printer.PrintObj(decodedObj, w); err != nil { if !errs.Has(err.Error()) { errs.Insert(err.Error()) allErrs = append(allErrs, err) } continue } } w.Flush() if printer != nil && lastMapping != nil { cmdutil.PrintFilterCount(filteredResourceCount, lastMapping.Resource, filterOpts) } return utilerrors.NewAggregate(allErrs) }
func RunStatus(f cmdutil.Factory, cmd *cobra.Command, out io.Writer, args []string, options *resource.FilenameOptions) error { if len(args) == 0 && cmdutil.IsFilenameEmpty(options.Filenames) { return cmdutil.UsageError(cmd, "Required resource not specified.") } mapper, typer := f.Object() cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err } r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, options). ResourceTypeOrNameArgs(true, args...). SingleResourceType(). Latest(). Do() err = r.Err() if err != nil { return err } infos, err := r.Infos() if err != nil { return err } if len(infos) != 1 { return fmt.Errorf("rollout status is only supported on individual resources and resource collections - %d resources were found", len(infos)) } info := infos[0] mapping := info.ResourceMapping() obj, err := r.Object() if err != nil { return err } rv, err := mapping.MetadataAccessor.ResourceVersion(obj) if err != nil { return err } statusViewer, err := f.StatusViewer(mapping) if err != nil { return err } revision := cmdutil.GetFlagInt64(cmd, "revision") if revision < 0 { return fmt.Errorf("revision must be a positive integer: %v", revision) } // check if deployment's has finished the rollout status, done, err := statusViewer.Status(cmdNamespace, info.Name, revision) if err != nil { return err } fmt.Fprintf(out, "%s", status) if done { return nil } shouldWatch := cmdutil.GetFlagBool(cmd, "watch") if !shouldWatch { return nil } // watch for changes to the deployment w, err := r.Watch(rv) if err != nil { return err } // if the rollout isn't done yet, keep watching deployment status intr := interrupt.New(nil, w.Stop) return intr.Run(func() error { _, err := watch.Until(0, w, func(e watch.Event) (bool, error) { // print deployment's status status, done, err := statusViewer.Status(cmdNamespace, info.Name, revision) if err != nil { return false, err } fmt.Fprintf(out, "%s", status) // Quit waiting if the rollout is done if done { return true, nil } return false, nil }) return err }) }