// 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 TestPullWithSecrets(t *testing.T) { // auth value is equivalent to: "username":"******","password":"******" dockerCfg := map[string]map[string]string{"index.docker.io/v1/": {"email": "passed-email", "auth": "cGFzc2VkLXVzZXI6cGFzc2VkLXBhc3N3b3Jk"}} dockercfgContent, err := json.Marshal(dockerCfg) if err != nil { t.Errorf("unexpected error: %v", err) } dockerConfigJson := map[string]map[string]map[string]string{"auths": dockerCfg} dockerConfigJsonContent, err := json.Marshal(dockerConfigJson) if err != nil { t.Errorf("unexpected error: %v", err) } tests := map[string]struct { imageName string passedSecrets []api.Secret builtInDockerConfig credentialprovider.DockerConfig expectedPulls []string }{ "no matching secrets": { "ubuntu", []api.Secret{}, credentialprovider.DockerConfig(map[string]credentialprovider.DockerConfigEntry{}), []string{"ubuntu:latest using {}"}, }, "default keyring secrets": { "ubuntu", []api.Secret{}, credentialprovider.DockerConfig(map[string]credentialprovider.DockerConfigEntry{"index.docker.io/v1/": {"built-in", "password", "email"}}), []string{`ubuntu:latest using {"username":"******","password":"******","email":"email"}`}, }, "default keyring secrets unused": { "ubuntu", []api.Secret{}, credentialprovider.DockerConfig(map[string]credentialprovider.DockerConfigEntry{"extraneous": {"built-in", "password", "email"}}), []string{`ubuntu:latest using {}`}, }, "builtin keyring secrets, but use passed": { "ubuntu", []api.Secret{{Type: api.SecretTypeDockercfg, Data: map[string][]byte{api.DockerConfigKey: dockercfgContent}}}, credentialprovider.DockerConfig(map[string]credentialprovider.DockerConfigEntry{"index.docker.io/v1/": {"built-in", "password", "email"}}), []string{`ubuntu:latest using {"username":"******","password":"******","email":"passed-email"}`}, }, "builtin keyring secrets, but use passed with new docker config": { "ubuntu", []api.Secret{{Type: api.SecretTypeDockerConfigJson, Data: map[string][]byte{api.DockerConfigJsonKey: dockerConfigJsonContent}}}, credentialprovider.DockerConfig(map[string]credentialprovider.DockerConfigEntry{"index.docker.io/v1/": {"built-in", "password", "email"}}), []string{`ubuntu:latest using {"username":"******","password":"******","email":"passed-email"}`}, }, } for _, test := range tests { builtInKeyRing := &credentialprovider.BasicDockerKeyring{} builtInKeyRing.Add(test.builtInDockerConfig) fakeClient := &FakeDockerClient{} dp := dockerPuller{ client: fakeClient, keyring: builtInKeyRing, } err := dp.Pull(test.imageName, test.passedSecrets) if err != nil { t.Errorf("unexpected non-nil err: %s", err) continue } if e, a := 1, len(fakeClient.pulled); e != a { t.Errorf("%s: expected 1 pulled image, got %d: %v", test.imageName, a, fakeClient.pulled) continue } if e, a := test.expectedPulls, fakeClient.pulled; !reflect.DeepEqual(e, a) { t.Errorf("%s: expected pull of %v, but got %v", test.imageName, e, a) } } }