package cmd import ( "fmt" "io" "strings" kapi "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/errors" ) func selectContainers(containers []kapi.Container, spec string) ([]*kapi.Container, []*kapi.Container) { out := []*kapi.Container{} skipped := []*kapi.Container{} for i, c := range containers { if selectString(c.Name, spec) { out = append(out, &containers[i]) } else { skipped = append(skipped, &containers[i]) } } return out, skipped } func handlePodUpdateError(out io.Writer, err error, resource string) { errored := false if statusError, ok := err.(*errors.StatusError); ok && errors.IsInvalid(err) { errorDetails := statusError.Status().Details if errorDetails.Kind == "Pod" { for _, cause := range errorDetails.Causes { if cause.Field == "spec" && strings.Contains(cause.Message, "may not update fields other than") { fmt.Fprintf(out, "Error updating pod %q: may not update %s in a pod directly\n", errorDetails.Name, resource) errored = true break } } } } if !errored { fmt.Fprintf(out, "error: %v\n", err) } } // selectString returns true if the provided string matches spec, where spec is a string with // a non-greedy '*' wildcard operator. // TODO: turn into a regex and handle greedy matches and backtracking. func selectString(s, spec string) bool { if spec == "*" { return true } if !strings.Contains(spec, "*") { return s == spec } pos := 0 match := true parts := strings.Split(spec, "*") for i, part := range parts { if len(part) == 0 { continue } next := strings.Index(s[pos:], part) switch { // next part not in string case next < pos: fallthrough // first part does not match start of string case i == 0 && pos != 0: fallthrough // last part does not exactly match remaining part of string case i == (len(parts)-1) && len(s) != (len(part)+next): match = false break default: pos = next } } return match }