func (ks KnownSecretType) Matches(secretContent map[string][]byte) bool { if secretContent == nil { return false } secretKeys := sets.StringKeySet(secretContent) return reflect.DeepEqual(ks.RequiredContents.List(), secretKeys.List()) }
// ListGroups queries for all groups as configured with the common group filter and returns their // LDAP group UIDs. This also satisfies the LDAPGroupLister interface func (e *ADLDAPInterface) ListGroups() ([]string, error) { if err := e.populateCache(); err != nil { return nil, err } return sets.StringKeySet(e.ldapGroupToLDAPMembers).List(), nil }
// Returns pods missing from summary. func podsMissingFromSummary(s stats.Summary, expectedPods sets.String) sets.String { expectedPods = sets.StringKeySet(expectedPods) for _, pod := range s.Pods { if expectedPods.Has(pod.PodRef.Name) { expectedPods.Delete(pod.PodRef.Name) } } return expectedPods }
func (c *threadSafeMap) AddIndexers(newIndexers Indexers) error { c.lock.Lock() defer c.lock.Unlock() if len(c.items) > 0 { return fmt.Errorf("cannot add indexers to running index") } oldKeys := sets.StringKeySet(c.indexers) newKeys := sets.StringKeySet(newIndexers) if oldKeys.HasAny(newKeys.List()...) { return fmt.Errorf("indexer conflict: %v", oldKeys.Intersection(newKeys)) } for k, v := range newIndexers { c.indexers[k] = v } return nil }
// TODO: profile this function to see if a naive N^2 algorithm performs better // when the number of references is small. func referencesDiffs(old []metatypes.OwnerReference, new []metatypes.OwnerReference) (added []metatypes.OwnerReference, removed []metatypes.OwnerReference) { oldUIDToRef := make(map[string]metatypes.OwnerReference) for i := 0; i < len(old); i++ { oldUIDToRef[string(old[i].UID)] = old[i] } oldUIDSet := sets.StringKeySet(oldUIDToRef) newUIDToRef := make(map[string]metatypes.OwnerReference) for i := 0; i < len(new); i++ { newUIDToRef[string(new[i].UID)] = new[i] } newUIDSet := sets.StringKeySet(newUIDToRef) addedUID := newUIDSet.Difference(oldUIDSet) removedUID := oldUIDSet.Difference(newUIDSet) for uid := range addedUID { added = append(added, newUIDToRef[uid]) } for uid := range removedUID { removed = append(removed, oldUIDToRef[uid]) } return added, removed }
// Returns volumes missing from summary. func volumesMissingFromSummary(s stats.Summary, expectedVolumes sets.String) sets.String { for _, pod := range s.Pods { expectedPodVolumes := sets.StringKeySet(expectedVolumes) for _, vs := range pod.VolumeStats { if expectedPodVolumes.Has(vs.Name) { expectedPodVolumes.Delete(vs.Name) } } if expectedPodVolumes.Len() != 0 { return expectedPodVolumes } } return sets.NewString() }
// execute an explicit task reconciliation, as per http://mesos.apache.org/documentation/latest/reconciliation/ func (k *framework) explicitlyReconcileTasks(driver bindings.SchedulerDriver, taskToSlave map[string]string, cancel <-chan struct{}) error { log.Info("explicit reconcile tasks") // tell mesos to send us the latest status updates for all the non-terminal tasks that we know about statusList := []*mesos.TaskStatus{} remaining := sets.StringKeySet(taskToSlave) for taskId, slaveId := range taskToSlave { if slaveId == "" { delete(taskToSlave, taskId) continue } statusList = append(statusList, &mesos.TaskStatus{ TaskId: mutil.NewTaskID(taskId), SlaveId: mutil.NewSlaveID(slaveId), State: mesos.TaskState_TASK_RUNNING.Enum(), // req'd field, doesn't have to reflect reality }) } select { case <-cancel: return merrors.ReconciliationCancelledErr default: if _, err := driver.ReconcileTasks(statusList); err != nil { return err } } start := time.Now() first := true for backoff := 1 * time.Second; first || remaining.Len() > 0; backoff = backoff * 2 { first = false // nothing to do here other than wait for status updates.. if backoff > k.schedulerConfig.ExplicitReconciliationMaxBackoff.Duration { backoff = k.schedulerConfig.ExplicitReconciliationMaxBackoff.Duration } select { case <-cancel: return merrors.ReconciliationCancelledErr case <-time.After(backoff): for taskId := range remaining { if task, _ := k.sched.Tasks().Get(taskId); task != nil && explicitTaskFilter(task) && task.UpdatedTime.Before(start) { // keep this task in remaining list continue } remaining.Delete(taskId) } } } return nil }
func (m *Master) InstallAPIs(c *Config, restOptionsGetter genericapiserver.RESTOptionsGetter) { apiGroupsInfo := []genericapiserver.APIGroupInfo{} // Install third party resource support if requested // TODO seems like this bit ought to be unconditional and the REST API is controlled by the config if c.GenericConfig.APIResourceConfigSource.ResourceEnabled(extensionsapiv1beta1.SchemeGroupVersion.WithResource("thirdpartyresources")) { var err error // TODO figure out why this isn't a loopback client m.thirdPartyResourceServer.ThirdPartyStorageConfig, err = c.StorageFactory.NewConfig(extensions.Resource("thirdpartyresources")) if err != nil { glog.Fatalf("Error getting third party storage: %v", err) } } // stabilize order. // TODO find a better way to configure priority of groups for _, group := range sets.StringKeySet(c.RESTStorageProviders).List() { if !c.GenericConfig.APIResourceConfigSource.AnyResourcesForGroupEnabled(group) { glog.V(1).Infof("Skipping disabled API group %q.", group) continue } restStorageBuilder := c.RESTStorageProviders[group] apiGroupInfo, enabled := restStorageBuilder.NewRESTStorage(c.GenericConfig.APIResourceConfigSource, restOptionsGetter) if !enabled { glog.Warningf("Problem initializing API group %q, skipping.", group) continue } glog.V(1).Infof("Enabling API group %q.", group) if postHookProvider, ok := restStorageBuilder.(genericapiserver.PostStartHookProvider); ok { name, hook, err := postHookProvider.PostStartHook() if err != nil { glog.Fatalf("Error building PostStartHook: %v", err) } if err := m.GenericAPIServer.AddPostStartHook(name, hook); err != nil { glog.Fatalf("Error registering PostStartHook %q: %v", name, err) } } apiGroupsInfo = append(apiGroupsInfo, apiGroupInfo) } for i := range apiGroupsInfo { if err := m.GenericAPIServer.InstallAPIGroup(&apiGroupsInfo[i]); err != nil { glog.Fatalf("Error in registering group versions: %v", err) } } }
// handleLocationChange goes through all service account dockercfg secrets and updates them to point at a new docker-registry location func (e *DockerRegistryServiceController) handleLocationChange(serviceLocation string) error { e.dockercfgController.SetDockerURL(serviceLocation) dockercfgSecrets, err := e.listDockercfgSecrets() if err != nil { return err } for _, dockercfgSecret := range dockercfgSecrets { dockercfg := &credentialprovider.DockerConfig{} if err := json.Unmarshal(dockercfgSecret.Data[api.DockerConfigKey], dockercfg); err != nil { utilruntime.HandleError(err) continue } dockercfgMap := map[string]credentialprovider.DockerConfigEntry(*dockercfg) keys := sets.StringKeySet(dockercfgMap) if len(keys) != 1 { utilruntime.HandleError(err) continue } oldKey := keys.List()[0] // if there's no change, skip if oldKey == serviceLocation { continue } dockercfgMap[serviceLocation] = dockercfgMap[oldKey] delete(dockercfgMap, oldKey) t := credentialprovider.DockerConfig(dockercfgMap) dockercfg = &t dockercfgContent, err2 := json.Marshal(dockercfg) if err2 != nil { utilruntime.HandleError(err2) continue } dockercfgSecret.Data[api.DockerConfigKey] = dockercfgContent if _, updateErr := e.client.Secrets(dockercfgSecret.Namespace).Update(dockercfgSecret); updateErr != nil { utilruntime.HandleError(updateErr) continue } } return err }
func DescribePolicy(policy *authorizationapi.Policy) (string, error) { return tabbedString(func(out *tabwriter.Writer) error { formatMeta(out, policy.ObjectMeta) formatString(out, "Last Modified", policy.LastModified) // using .List() here because I always want the sorted order that it provides for _, key := range sets.StringKeySet(policy.Roles).List() { role := policy.Roles[key] fmt.Fprint(out, key+"\t"+PolicyRuleHeadings+"\n") for _, rule := range role.Rules { DescribePolicyRule(out, rule, "\t") } } return nil }) }
func (o *PatchOptions) Complete(f *clientcmd.Factory, cmd *cobra.Command, args []string) error { if len(args) != 1 { return fmt.Errorf("exactly one FILENAME is allowed: %v", args) } o.Filename = args[0] patchTypeString := strings.ToLower(cmdutil.GetFlagString(cmd, "type")) ok := false o.PatchType, ok = patchTypes[patchTypeString] if !ok { return cmdutil.UsageError(cmd, fmt.Sprintf("--type must be one of %v, not %q", sets.StringKeySet(patchTypes).List(), patchTypeString)) } o.Builder = resource.NewBuilder(configapiinstall.NewRESTMapper(), configapi.Scheme, resource.DisabledClientForMapping{}, configapi.Codecs.LegacyCodec()) return nil }
func newNavigationSteps(path string) (*navigationSteps, error) { steps := []navigationStep{} individualParts := strings.Split(path, ".") currType := reflect.TypeOf(clientcmdapi.Config{}) currPartIndex := 0 for currPartIndex < len(individualParts) { switch currType.Kind() { case reflect.Map: // if we're in a map, we need to locate a name. That name may contain dots, so we need to know what tokens are legal for the map's value type // for example, we could have a set request like: `set clusters.10.10.12.56.insecure-skip-tls-verify true`. We enter this case with // steps representing 10, 10, 12, 56, insecure-skip-tls-verify. The name is "10.10.12.56", so we want to collect all those parts together and // store them as a single step. In order to do that, we need to determine what set of tokens is a legal step AFTER the name of the map key // This set of reflective code pulls the type of the map values, uses that type to look up the set of legal tags. Those legal tags are used to // walk the list of remaining parts until we find a match to a legal tag or the end of the string. That name is used to burn all the used parts. mapValueType := currType.Elem().Elem() mapValueOptions, err := getPotentialTypeValues(mapValueType) if err != nil { return nil, err } nextPart := findNameStep(individualParts[currPartIndex:], sets.StringKeySet(mapValueOptions)) steps = append(steps, navigationStep{nextPart, mapValueType}) currPartIndex += len(strings.Split(nextPart, ".")) currType = mapValueType case reflect.Struct: nextPart := individualParts[currPartIndex] options, err := getPotentialTypeValues(currType) if err != nil { return nil, err } fieldType, exists := options[nextPart] if !exists { return nil, fmt.Errorf("unable to parse %v after %v at %v", path, steps, currType) } steps = append(steps, navigationStep{nextPart, fieldType}) currPartIndex += len(strings.Split(nextPart, ".")) currType = fieldType } } return &navigationSteps{steps, 0}, nil }
func TestDiscoveryGroupVersions(t *testing.T) { testutil.RequireEtcd(t) defer testutil.DumpEtcdOnFailure(t) _, clusterAdminKubeConfig, err := testserver.StartTestMasterAPI() if err != nil { t.Fatalf("unexpected error starting test master: %v", err) } clusterAdminKubeClient, err := testutil.GetClusterAdminKubeClient(clusterAdminKubeConfig) if err != nil { t.Fatalf("unexpected error: %v", err) } resources, err := clusterAdminKubeClient.Discovery().ServerResources() if err != nil { t.Fatalf("unexpected error: %v", err) } for _, resource := range resources { gv, err := unversioned.ParseGroupVersion(resource.GroupVersion) if err != nil { continue } allowedVersions := sets.NewString(configapi.KubeAPIGroupsToAllowedVersions[gv.Group]...) if !allowedVersions.Has(gv.Version) { t.Errorf("Disallowed group/version found in discovery: %#v", gv) } } expectedGroupVersions := sets.NewString() for group, versions := range configapi.KubeAPIGroupsToAllowedVersions { for _, version := range versions { expectedGroupVersions.Insert(unversioned.GroupVersion{Group: group, Version: version}.String()) } } discoveredGroupVersions := sets.StringKeySet(resources) if !reflect.DeepEqual(discoveredGroupVersions, expectedGroupVersions) { t.Fatalf("Expected %#v, got %#v", expectedGroupVersions.List(), discoveredGroupVersions.List()) } }
// TestRunGenerators makes sure we catch new generators added to `oc run` func TestRunGenerators(t *testing.T) { f := NewFactory(nil) // Contains the run generators we expect to see expectedRunGenerators := sets.NewString( // kube generators "run/v1", "run-pod/v1", "deployment/v1beta1", "job/v1", "job/v1beta1", // origin generators "run-controller/v1", // legacy alias for run/v1 "deploymentconfig/v1", ).List() runGenerators := sets.StringKeySet(f.Generators("run")).List() if !reflect.DeepEqual(expectedRunGenerators, runGenerators) { t.Errorf("Expected run generators:%#v, got:\n%#v", expectedRunGenerators, runGenerators) } }
func DescribePolicyBinding(policyBinding *authorizationapi.PolicyBinding) (string, error) { return tabbedString(func(out *tabwriter.Writer) error { formatMeta(out, policyBinding.ObjectMeta) formatString(out, "Last Modified", policyBinding.LastModified) formatString(out, "Policy", policyBinding.PolicyRef.Namespace) // using .List() here because I always want the sorted order that it provides for _, key := range sets.StringKeySet(policyBinding.RoleBindings).List() { roleBinding := policyBinding.RoleBindings[key] users, groups, sas, others := authorizationapi.SubjectsStrings(roleBinding.Namespace, roleBinding.Subjects) formatString(out, "RoleBinding["+key+"]", " ") formatString(out, "\tRole", roleBinding.RoleRef.Name) formatString(out, "\tUsers", strings.Join(users, ", ")) formatString(out, "\tGroups", strings.Join(groups, ", ")) formatString(out, "\tServiceAccounts", strings.Join(sas, ", ")) formatString(out, "\tSubjects", strings.Join(others, ", ")) } return nil }) }
func (e *DockerRegistryServiceController) syncSecretUpdate(key string) error { obj, exists, err := e.secretCache.GetByKey(key) if err != nil { utilruntime.HandleError(fmt.Errorf("Unable to retrieve secret %v from store: %v", key, err)) return err } if !exists { return nil } dockerRegistryURLs := e.getRegistryURLs() sharedDockercfgSecret := obj.(*kapi.Secret) dockercfg := &credentialprovider.DockerConfig{} // an error here doesn't matter. If we can't deserialize this, we'll replace it with one that works. json.Unmarshal(sharedDockercfgSecret.Data[kapi.DockerConfigKey], dockercfg) dockercfgMap := map[string]credentialprovider.DockerConfigEntry(*dockercfg) existingDockercfgSecretLocations := sets.StringKeySet(dockercfgMap) // if the existingDockercfgSecretLocations haven't changed, don't make an update and check the next one if existingDockercfgSecretLocations.Equal(dockerRegistryURLs) { return nil } // we need to update it, make a copy uncastObj, err := kapi.Scheme.DeepCopy(obj) if err != nil { return err } dockercfgSecret := uncastObj.(*kapi.Secret) dockerCredentials := dockercfgSecret.Annotations[ServiceAccountTokenValueAnnotation] if len(dockerCredentials) == 0 && len(existingDockercfgSecretLocations) > 0 { dockerCredentials = dockercfgMap[existingDockercfgSecretLocations.List()[0]].Password } if len(dockerCredentials) == 0 { tokenSecretKey := dockercfgSecret.Namespace + "/" + dockercfgSecret.Annotations[ServiceAccountTokenSecretNameKey] tokenSecret, exists, err := e.secretCache.GetByKey(tokenSecretKey) if !exists { utilruntime.HandleError(fmt.Errorf("cannot determine SA token due to missing secret: %v", tokenSecretKey)) return nil } if err != nil { utilruntime.HandleError(fmt.Errorf("cannot determine SA token: %v", err)) return nil } dockerCredentials = string(tokenSecret.(*kapi.Secret).Data[kapi.ServiceAccountTokenKey]) } newDockercfgMap := credentialprovider.DockerConfig{} for key := range dockerRegistryURLs { newDockercfgMap[key] = credentialprovider.DockerConfigEntry{ Username: "******", Password: dockerCredentials, Email: "*****@*****.**", } } dockercfgContent, err := json.Marshal(&newDockercfgMap) if err != nil { utilruntime.HandleError(err) return nil } dockercfgSecret.Data[kapi.DockerConfigKey] = dockercfgContent if _, err := e.client.Secrets(dockercfgSecret.Namespace).Update(dockercfgSecret); err != nil { return err } return nil }
func NewCmdPatch(f cmdutil.Factory, out io.Writer) *cobra.Command { options := &PatchOptions{} // retrieve a list of handled resources from printer as valid args validArgs, argAliases := []string{}, []string{} p, err := f.Printer(nil, kubectl.PrintOptions{ ColumnLabels: []string{}, }) cmdutil.CheckErr(err) if p != nil { validArgs = p.HandledResources() argAliases = kubectl.ResourceAliases(validArgs) } cmd := &cobra.Command{ Use: "patch (-f FILENAME | TYPE NAME) -p PATCH", Short: "Update field(s) of a resource using strategic merge patch", Long: patch_long, Example: patch_example, Run: func(cmd *cobra.Command, args []string) { options.OutputFormat = cmdutil.GetFlagString(cmd, "output") err := RunPatch(f, out, cmd, args, options) cmdutil.CheckErr(err) }, ValidArgs: validArgs, ArgAliases: argAliases, } cmd.Flags().StringP("patch", "p", "", "The patch to be applied to the resource JSON file.") cmd.MarkFlagRequired("patch") cmd.Flags().String("type", "strategic", fmt.Sprintf("The type of patch being provided; one of %v", sets.StringKeySet(patchTypes).List())) cmdutil.AddPrinterFlags(cmd) cmdutil.AddRecordFlag(cmd) cmdutil.AddInclude3rdPartyFlags(cmd) usage := "identifying the resource to update" cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage) cmd.Flags().BoolVar(&options.Local, "local", false, "If true, patch will operate on the content of the file, not the server-side resource.") return cmd }
func RunPatch(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, shortOutput bool, options *PatchOptions) error { cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err } patchType := api.StrategicMergePatchType patchTypeString := strings.ToLower(cmdutil.GetFlagString(cmd, "type")) if len(patchTypeString) != 0 { ok := false patchType, ok = patchTypes[patchTypeString] if !ok { return cmdutil.UsageError(cmd, fmt.Sprintf("--type must be one of %v, not %q", sets.StringKeySet(patchTypes).List(), patchTypeString)) } } patch := cmdutil.GetFlagString(cmd, "patch") if len(patch) == 0 { return cmdutil.UsageError(cmd, "Must specify -p to patch") } patchBytes, err := yaml.ToJSON([]byte(patch)) if err != nil { return fmt.Errorf("unable to parse %q: %v", patch, err) } mapper, typer := f.Object(cmdutil.GetIncludeThirdPartyAPIs(cmd)) r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, options.Recursive, options.Filenames...). ResourceTypeOrNameArgs(false, args...). Flatten(). Do() err = r.Err() if err != nil { return err } count := 0 err = r.Visit(func(info *resource.Info, err error) error { if err != nil { return err } name, namespace := info.Name, info.Namespace mapping := info.ResourceMapping() client, err := f.ClientForMapping(mapping) if err != nil { return err } helper := resource.NewHelper(client, mapping) patchedObject, err := helper.Patch(namespace, name, patchType, patchBytes) if err != nil { return err } if cmdutil.ShouldRecord(cmd, info) { if err := cmdutil.RecordChangeCause(patchedObject, f.Command()); err == nil { // don't return an error on failure. The patch itself succeeded, its only the hint for that change that failed // don't bother checking for failures of this replace, because a failure to indicate the hint doesn't fail the command // also, don't force the replacement. If the replacement fails on a resourceVersion conflict, then it means this // record hint is likely to be invalid anyway, so avoid the bad hint resource.NewHelper(client, mapping).Replace(namespace, name, false, patchedObject) } } count++ cmdutil.PrintSuccess(mapper, shortOutput, out, "", name, "patched") return nil }) if err != nil { return err } if count == 0 { return fmt.Errorf("no objects passed to patch") } return nil }
// Map of group names to allowed REST API versions KubeAPIGroupsToAllowedVersions = map[string][]string{ APIGroupKube: {"v1"}, APIGroupExtensions: {"v1beta1"}, APIGroupAutoscaling: {"v1"}, APIGroupBatch: {"v1"}, } // Map of group names to known, but disallowed REST API versions KubeAPIGroupsToDeadVersions = map[string][]string{ APIGroupKube: {"v1beta3"}, APIGroupExtensions: {}, APIGroupAutoscaling: {}, APIGroupBatch: {}, } KnownKubeAPIGroups = sets.StringKeySet(KubeAPIGroupsToAllowedVersions) // FeatureAliases maps deprecated names of feature flag to their canonical // names. Aliases must be lower-cased for O(1) lookup. FeatureAliases = map[string]string{ "s2i builder": FeatureS2I, "web console": FeatureWebConsole, } KnownOpenShiftFeatures = []string{FeatureBuilder, FeatureS2I, FeatureWebConsole} AtomicDisabledFeatures = []string{FeatureBuilder, FeatureS2I, FeatureWebConsole} ) type ExtendedArguments map[string][]string // NodeConfig is the fully specified config starting an OpenShift node type NodeConfig struct {
func RunPatch(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *PatchOptions) error { switch { case options.Local && len(args) != 0: return fmt.Errorf("cannot specify --local and server resources") } cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err } patchType := api.StrategicMergePatchType patchTypeString := strings.ToLower(cmdutil.GetFlagString(cmd, "type")) if len(patchTypeString) != 0 { ok := false patchType, ok = patchTypes[patchTypeString] if !ok { return cmdutil.UsageError(cmd, fmt.Sprintf("--type must be one of %v, not %q", sets.StringKeySet(patchTypes).List(), patchTypeString)) } } patch := cmdutil.GetFlagString(cmd, "patch") if len(patch) == 0 { return cmdutil.UsageError(cmd, "Must specify -p to patch") } patchBytes, err := yaml.ToJSON([]byte(patch)) if err != nil { return fmt.Errorf("unable to parse %q: %v", patch, err) } mapper, typer := f.Object() r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, &options.FilenameOptions). ResourceTypeOrNameArgs(false, args...). Flatten(). Do() err = r.Err() if err != nil { return err } count := 0 err = r.Visit(func(info *resource.Info, err error) error { if err != nil { return err } name, namespace := info.Name, info.Namespace mapping := info.ResourceMapping() client, err := f.ClientForMapping(mapping) if err != nil { return err } if !options.Local { helper := resource.NewHelper(client, mapping) _, err := helper.Patch(namespace, name, patchType, patchBytes) if err != nil { return err } if cmdutil.ShouldRecord(cmd, info) { // don't return an error on failure. The patch itself succeeded, its only the hint for that change that failed // don't bother checking for failures of this replace, because a failure to indicate the hint doesn't fail the command // also, don't force the replacement. If the replacement fails on a resourceVersion conflict, then it means this // record hint is likely to be invalid anyway, so avoid the bad hint patch, err := cmdutil.ChangeResourcePatch(info, f.Command()) if err == nil { helper.Patch(info.Namespace, info.Name, api.StrategicMergePatchType, patch) } } count++ if options.OutputFormat == "name" || len(options.OutputFormat) == 0 { cmdutil.PrintSuccess(mapper, options.OutputFormat == "name", out, "", name, false, "patched") } return nil } count++ patchedObj, err := api.Scheme.DeepCopy(info.VersionedObject) if err != nil { return err } originalObjJS, err := runtime.Encode(api.Codecs.LegacyCodec(mapping.GroupVersionKind.GroupVersion()), info.VersionedObject.(runtime.Object)) if err != nil { return err } originalPatchedObjJS, err := getPatchedJSON(patchType, originalObjJS, patchBytes, patchedObj.(runtime.Object)) if err != nil { return err } targetObj, err := runtime.Decode(api.Codecs.UniversalDecoder(), originalPatchedObjJS) if err != nil { return err } // TODO: if we ever want to go generic, this allows a clean -o yaml without trying to print columns or anything // rawExtension := &runtime.Unknown{ // Raw: originalPatchedObjJS, // } printer, err := f.PrinterForMapping(cmd, mapping, false) if err != nil { return err } if err := printer.PrintObj(targetObj, out); err != nil { return err } return nil }) if err != nil { return err } if count == 0 { return fmt.Errorf("no objects passed to patch") } return nil }
func NewCmdPatch(f *cmdutil.Factory, out io.Writer) *cobra.Command { options := &PatchOptions{} // retrieve a list of handled resources from printer as valid args validArgs, argAliases := []string{}, []string{} p, err := f.Printer(nil, nil) cmdutil.CheckErr(err) if p != nil { validArgs = p.HandledResources() argAliases = kubectl.ResourceAliases(validArgs) } cmd := &cobra.Command{ Use: "patch (-f FILENAME | TYPE NAME) -p PATCH", Short: "Update field(s) of a resource using strategic merge patch.", Long: patch_long, Example: patch_example, Run: func(cmd *cobra.Command, args []string) { cmdutil.CheckErr(cmdutil.ValidateOutputArgs(cmd)) shortOutput := cmdutil.GetFlagString(cmd, "output") == "name" err := RunPatch(f, out, cmd, args, shortOutput, options) cmdutil.CheckErr(err) }, ValidArgs: validArgs, ArgAliases: argAliases, } cmd.Flags().StringP("patch", "p", "", "The patch to be applied to the resource JSON file.") cmd.MarkFlagRequired("patch") 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) cmdutil.AddRecursiveFlag(cmd, &options.Recursive) return cmd }
func NewCmdPatch(f *cmdutil.Factory, out io.Writer) *cobra.Command { options := &PatchOptions{} cmd := &cobra.Command{ Use: "patch (-f FILENAME | TYPE NAME) -p PATCH", Short: "Update field(s) of a resource using strategic merge patch.", Long: patch_long, Example: patch_example, Run: func(cmd *cobra.Command, args []string) { cmdutil.CheckErr(cmdutil.ValidateOutputArgs(cmd)) shortOutput := cmdutil.GetFlagString(cmd, "output") == "name" err := RunPatch(f, out, cmd, args, shortOutput, options) cmdutil.CheckErr(err) }, } cmd.Flags().StringP("patch", "p", "", "The patch to be applied to the resource JSON file.") cmd.MarkFlagRequired("patch") 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) usage := "Filename, directory, or URL to a file identifying the resource to update" kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) return cmd }
func NewCmdPatch(name, fullName string, f *clientcmd.Factory, out io.Writer) *cobra.Command { o := &PatchOptions{Out: out} cmd := &cobra.Command{ Use: name + " FILENAME -p PATCH", Short: "Update field(s) of a resource using a patch.", Long: patch_long, Example: patch_example, Run: func(cmd *cobra.Command, args []string) { cmdutil.CheckErr(o.Complete(f, cmd, args)) cmdutil.CheckErr(o.Validate()) cmdutil.CheckErr(o.RunPatch()) }, } cmd.Flags().StringVarP(&o.Patch, "patch", "p", "", "The patch to be applied to the resource JSON file.") cmd.MarkFlagRequired("patch") cmd.Flags().String("type", "strategic", fmt.Sprintf("The type of patch being provided; one of %v", sets.StringKeySet(patchTypes).List())) return cmd }
func (m *Master) InstallAPIs(c *Config) { apiGroupsInfo := []genericapiserver.APIGroupInfo{} // Install v1 unless disabled. if c.APIResourceConfigSource.AnyResourcesForVersionEnabled(apiv1.SchemeGroupVersion) { // Install v1 API. m.initV1ResourcesStorage(c) apiGroupInfo := genericapiserver.APIGroupInfo{ GroupMeta: *registered.GroupOrDie(api.GroupName), VersionedResourcesStorageMap: map[string]map[string]rest.Storage{ "v1": m.v1ResourcesStorage, }, IsLegacyGroup: true, Scheme: api.Scheme, ParameterCodec: api.ParameterCodec, NegotiatedSerializer: api.Codecs, } if autoscalingGroupVersion := (unversioned.GroupVersion{Group: "autoscaling", Version: "v1"}); registered.IsEnabledVersion(autoscalingGroupVersion) { apiGroupInfo.SubresourceGroupVersionKind = map[string]unversioned.GroupVersionKind{ "replicationcontrollers/scale": autoscalingGroupVersion.WithKind("Scale"), } } apiGroupsInfo = append(apiGroupsInfo, apiGroupInfo) } // Run the tunneler. healthzChecks := []healthz.HealthzChecker{} if m.tunneler != nil { m.tunneler.Run(m.getNodeAddresses) healthzChecks = append(healthzChecks, healthz.NamedCheck("SSH Tunnel Check", m.IsTunnelSyncHealthy)) prometheus.NewGaugeFunc(prometheus.GaugeOpts{ Name: "apiserver_proxy_tunnel_sync_latency_secs", Help: "The time since the last successful synchronization of the SSH tunnels for proxy requests.", }, func() float64 { return float64(m.tunneler.SecondsSinceSync()) }) } healthz.InstallHandler(m.MuxHelper, healthzChecks...) if c.EnableProfiling { m.MuxHelper.HandleFunc("/metrics", MetricsWithReset) } else { m.MuxHelper.HandleFunc("/metrics", defaultMetricsHandler) } // Install third party resource support if requested // TODO seems like this bit ought to be unconditional and the REST API is controlled by the config if c.APIResourceConfigSource.ResourceEnabled(extensionsapiv1beta1.SchemeGroupVersion.WithResource("thirdpartyresources")) { var err error m.thirdPartyStorage, err = c.StorageFactory.New(extensions.Resource("thirdpartyresources")) if err != nil { glog.Fatalf("Error getting third party storage: %v", err) } m.thirdPartyResources = map[string]thirdPartyEntry{} } restOptionsGetter := func(resource unversioned.GroupResource) generic.RESTOptions { return m.GetRESTOptionsOrDie(c, resource) } // stabilize order. // TODO find a better way to configure priority of groups for _, group := range sets.StringKeySet(c.RESTStorageProviders).List() { if !c.APIResourceConfigSource.AnyResourcesForGroupEnabled(group) { continue } restStorageBuilder := c.RESTStorageProviders[group] apiGroupInfo, enabled := restStorageBuilder.NewRESTStorage(c.APIResourceConfigSource, restOptionsGetter) if !enabled { continue } apiGroupsInfo = append(apiGroupsInfo, apiGroupInfo) } if err := m.InstallAPIGroups(apiGroupsInfo); err != nil { glog.Fatalf("Error in registering group versions: %v", err) } }
func RunPatch(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, shortOutput bool, options *PatchOptions) error { cmdNamespace, enforceNamespace, err := f.DefaultNamespace() if err != nil { return err } patchType := api.StrategicMergePatchType patchTypeString := strings.ToLower(cmdutil.GetFlagString(cmd, "type")) if len(patchTypeString) != 0 { ok := false patchType, ok = patchTypes[patchTypeString] if !ok { return cmdutil.UsageError(cmd, fmt.Sprintf("--type must be one of %v, not %q", sets.StringKeySet(patchTypes).List(), patchTypeString)) } } patch := cmdutil.GetFlagString(cmd, "patch") if len(patch) == 0 { return cmdutil.UsageError(cmd, "Must specify -p to patch") } patchBytes, err := yaml.ToJSON([]byte(patch)) if err != nil { return fmt.Errorf("unable to parse %q: %v", patch, err) } mapper, typer := f.Object() r := resource.NewBuilder(mapper, typer, resource.ClientMapperFunc(f.ClientForMapping), f.Decoder(true)). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(enforceNamespace, options.Filenames...). ResourceTypeOrNameArgs(false, args...). Flatten(). 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("multiple resources provided") } info := infos[0] name, namespace := info.Name, info.Namespace mapping := info.ResourceMapping() client, err := f.ClientForMapping(mapping) if err != nil { return err } helper := resource.NewHelper(client, mapping) _, err = helper.Patch(namespace, name, patchType, patchBytes) if err != nil { return err } if cmdutil.ShouldRecord(cmd, info) { patchBytes, err = cmdutil.ChangeResourcePatch(info, f.Command()) if err != nil { return err } _, err = helper.Patch(namespace, name, api.StrategicMergePatchType, patchBytes) if err != nil { return err } } cmdutil.PrintSuccess(mapper, shortOutput, out, "", name, "patched") return nil }
func (m *Master) InstallAPIs(c *Config) { apiGroupsInfo := []genericapiserver.APIGroupInfo{} // Install v1 unless disabled. if c.APIResourceConfigSource.AnyResourcesForVersionEnabled(apiv1.SchemeGroupVersion) { // Install v1 API. m.initV1ResourcesStorage(c) apiGroupInfo := genericapiserver.APIGroupInfo{ GroupMeta: *registered.GroupOrDie(api.GroupName), VersionedResourcesStorageMap: map[string]map[string]rest.Storage{ "v1": m.v1ResourcesStorage, }, IsLegacyGroup: true, Scheme: api.Scheme, ParameterCodec: api.ParameterCodec, NegotiatedSerializer: api.Codecs, SubresourceGroupVersionKind: map[string]unversioned.GroupVersionKind{}, } if autoscalingGroupVersion := (unversioned.GroupVersion{Group: "autoscaling", Version: "v1"}); registered.IsEnabledVersion(autoscalingGroupVersion) { apiGroupInfo.SubresourceGroupVersionKind["replicationcontrollers/scale"] = autoscalingGroupVersion.WithKind("Scale") } if policyGroupVersion := (unversioned.GroupVersion{Group: "policy", Version: "v1alpha1"}); registered.IsEnabledVersion(policyGroupVersion) { apiGroupInfo.SubresourceGroupVersionKind["pods/eviction"] = policyGroupVersion.WithKind("Eviction") } apiGroupsInfo = append(apiGroupsInfo, apiGroupInfo) } // Run the tunneler. healthzChecks := []healthz.HealthzChecker{} if m.tunneler != nil { m.tunneler.Run(m.getNodeAddresses) healthzChecks = append(healthzChecks, healthz.NamedCheck("SSH Tunnel Check", m.IsTunnelSyncHealthy)) prometheus.NewGaugeFunc(prometheus.GaugeOpts{ Name: "apiserver_proxy_tunnel_sync_latency_secs", Help: "The time since the last successful synchronization of the SSH tunnels for proxy requests.", }, func() float64 { return float64(m.tunneler.SecondsSinceSync()) }) } healthz.InstallHandler(m.MuxHelper, healthzChecks...) if c.EnableProfiling { m.MuxHelper.HandleFunc("/metrics", MetricsWithReset) } else { m.MuxHelper.HandleFunc("/metrics", defaultMetricsHandler) } // Install third party resource support if requested // TODO seems like this bit ought to be unconditional and the REST API is controlled by the config if c.APIResourceConfigSource.ResourceEnabled(extensionsapiv1beta1.SchemeGroupVersion.WithResource("thirdpartyresources")) { var err error m.thirdPartyStorageConfig, err = c.StorageFactory.NewConfig(extensions.Resource("thirdpartyresources")) if err != nil { glog.Fatalf("Error getting third party storage: %v", err) } m.thirdPartyResources = map[string]*thirdPartyEntry{} } restOptionsGetter := func(resource unversioned.GroupResource) generic.RESTOptions { return m.GetRESTOptionsOrDie(c, resource) } // stabilize order. // TODO find a better way to configure priority of groups for _, group := range sets.StringKeySet(c.RESTStorageProviders).List() { if !c.APIResourceConfigSource.AnyResourcesForGroupEnabled(group) { glog.V(1).Infof("Skipping disabled API group %q.", group) continue } restStorageBuilder := c.RESTStorageProviders[group] apiGroupInfo, enabled := restStorageBuilder.NewRESTStorage(c.APIResourceConfigSource, restOptionsGetter) if !enabled { glog.Warningf("Problem initializing API group %q, skipping.", group) continue } glog.V(1).Infof("Enabling API group %q.", group) // This is here so that, if the policy group is present, the eviction // subresource handler wil be able to find poddisruptionbudgets // TODO(lavalamp) find a better way for groups to discover and interact // with each other if group == "policy" { storage := apiGroupsInfo[0].VersionedResourcesStorageMap["v1"]["pods/eviction"] evictionStorage := storage.(*podetcd.EvictionREST) storage = apiGroupInfo.VersionedResourcesStorageMap["v1alpha1"]["poddisruptionbudgets"] evictionStorage.PodDisruptionBudgetLister = storage.(rest.Lister) evictionStorage.PodDisruptionBudgetUpdater = storage.(rest.Updater) } apiGroupsInfo = append(apiGroupsInfo, apiGroupInfo) } if err := m.InstallAPIGroups(apiGroupsInfo); err != nil { glog.Fatalf("Error in registering group versions: %v", err) } }
func (m *Master) InstallAPIs(c *Config) { restOptionsGetter := func(resource unversioned.GroupResource) generic.RESTOptions { return m.restOptionsFactory.NewFor(resource) } apiGroupsInfo := []genericapiserver.APIGroupInfo{} // Install v1 unless disabled. if c.GenericConfig.APIResourceConfigSource.AnyResourcesForVersionEnabled(apiv1.SchemeGroupVersion) { legacyRESTStorage, apiGroupInfo, err := m.legacyRESTStorageProvider.NewLegacyRESTStorage(restOptionsGetter) if err != nil { glog.Fatalf("Error building core storage: %v", err) } m.legacyRESTStorage = legacyRESTStorage apiGroupsInfo = append(apiGroupsInfo, apiGroupInfo) } // Run the tunneler. healthzChecks := []healthz.HealthzChecker{} if m.tunneler != nil { m.tunneler.Run(m.getNodeAddresses) healthzChecks = append(healthzChecks, healthz.NamedCheck("SSH Tunnel Check", m.IsTunnelSyncHealthy)) prometheus.NewGaugeFunc(prometheus.GaugeOpts{ Name: "apiserver_proxy_tunnel_sync_latency_secs", Help: "The time since the last successful synchronization of the SSH tunnels for proxy requests.", }, func() float64 { return float64(m.tunneler.SecondsSinceSync()) }) } healthz.InstallHandler(&m.HandlerContainer.NonSwaggerRoutes, healthzChecks...) if c.GenericConfig.EnableProfiling { routes.MetricsWithReset{}.Install(m.HandlerContainer) } else { routes.DefaultMetrics{}.Install(m.HandlerContainer) } // Install third party resource support if requested // TODO seems like this bit ought to be unconditional and the REST API is controlled by the config if c.GenericConfig.APIResourceConfigSource.ResourceEnabled(extensionsapiv1beta1.SchemeGroupVersion.WithResource("thirdpartyresources")) { var err error m.thirdPartyStorageConfig, err = c.StorageFactory.NewConfig(extensions.Resource("thirdpartyresources")) if err != nil { glog.Fatalf("Error getting third party storage: %v", err) } m.thirdPartyResources = map[string]*thirdPartyEntry{} } // stabilize order. // TODO find a better way to configure priority of groups for _, group := range sets.StringKeySet(c.RESTStorageProviders).List() { if !c.GenericConfig.APIResourceConfigSource.AnyResourcesForGroupEnabled(group) { glog.V(1).Infof("Skipping disabled API group %q.", group) continue } restStorageBuilder := c.RESTStorageProviders[group] apiGroupInfo, enabled := restStorageBuilder.NewRESTStorage(c.GenericConfig.APIResourceConfigSource, restOptionsGetter) if !enabled { glog.Warningf("Problem initializing API group %q, skipping.", group) continue } glog.V(1).Infof("Enabling API group %q.", group) if postHookProvider, ok := restStorageBuilder.(genericapiserver.PostStartHookProvider); ok { name, hook, err := postHookProvider.PostStartHook() if err != nil { glog.Fatalf("Error building PostStartHook: %v", err) } if err := m.GenericAPIServer.AddPostStartHook(name, hook); err != nil { glog.Fatalf("Error registering PostStartHook %q: %v", name, err) } } apiGroupsInfo = append(apiGroupsInfo, apiGroupInfo) } for i := range apiGroupsInfo { if err := m.InstallAPIGroup(&apiGroupsInfo[i]); err != nil { glog.Fatalf("Error in registering group versions: %v", err) } } }