Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GetAll -> Get to retrieve credentials from credential helpers #840

Merged
merged 2 commits into from
Feb 16, 2018

Conversation

dekkagaijin
Copy link
Contributor

@dekkagaijin dekkagaijin commented Jan 26, 2018

- What I did
Improved docker build times.

- How I did it
Only request credentials for the configured registry from the corresponding credential helper, rather than doing a GetAll for each one.

- How to verify it
Build some toy image with several credential helpers configured...

jsand@jsand:~/go/src/github.com/docker/cli$ time docker build ~/gcloud-cred-helper-test
Sending build context to Docker daemon   5.12kB
Step 1/7 : FROM node:8
 ---> b87c2ad8344d
Step 2/7 : WORKDIR /usr/src/app
 ---> Using cache
 ---> b27c87b196eb
Step 3/7 : COPY package*.json ./
COPY failed: no source files were specified

real	1m28.929s
user	0m54.868s
sys	0m10.988s
jsand@jsand:~/go/src/github.com/docker/cli$ time ./build/docker build ~/gcloud-cred-helper-test
Sending build context to Docker daemon   5.12kB
Step 1/7 : FROM node:8
 ---> b87c2ad8344d
Step 2/7 : WORKDIR /usr/src/app
 ---> Using cache
 ---> b27c87b196eb
Step 3/7 : COPY package*.json ./
COPY failed: no source files were specified

real	0m7.137s
user	0m4.408s
sys	0m0.884s

- Description for the changelog
docker build now runs faster when registry-specific credential helper(s) are configured.

10/10 good doggo

@codecov-io
Copy link

codecov-io commented Jan 26, 2018

Codecov Report

Merging #840 into master will increase coverage by 0.08%.
The diff coverage is 64.7%.

@@            Coverage Diff             @@
##           master     #840      +/-   ##
==========================================
+ Coverage   52.93%   53.02%   +0.08%     
==========================================
  Files         245      244       -1     
  Lines       15848    15829      -19     
==========================================
+ Hits         8389     8393       +4     
+ Misses       6905     6884      -21     
+ Partials      554      552       -2

Copy link
Contributor

@dnephin dnephin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! In general it probably makes sense to only query for the specific credentials.

I have a couple questions about this change.

stripped = strings.TrimPrefix(serverAddress, "http://")
} else if strings.HasPrefix(serverAddress, "https://") {
stripped = strings.TrimPrefix(serverAddress, "https://")
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably use registry.ConvertToHostname(), although I'm not sure this is the correct place to do the convert.

How is this related to the rest of the change?


// Auth configs from a registry-specific helper should override those from the default store.
for registryHostname := range configFile.CredentialHelpers {
serverAddress := "https://" + registryHostname
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this necessary? From what I can tell other callers of GetAuthConfig() seem to be calling it with a url that doesn't have a scheme.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Keys in configFile.CredentialHelpers field are schemeless, whereas keys in configFile.AuthConfigs (and which back the default file store) contain the scheme. I see that the file store is now stripping the scheme from the auths entries with registry.ConvertToHostname() in file_store, so I'll remove this code here.

@dekkagaijin
Copy link
Contributor Author

Done...

configFile.AuthConfigs["https://"+testFileStoreServerAddress] = expectedFileStoreAuth

newNativeStore = func(configFile *ConfigFile, helperSuffix string) credentials.Store {
return NewMockNativeStore(map[string]types.AuthConfig{testCredHelperServerAddress: expectedCredHelperAuth})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this probably contain some extra key/values so that the test shows that not everything is being returned.

}

func (c *mockNativeStore) GetAll() (map[string]types.AuthConfig, error) {
c.GetAllCallCount = c.GetAllCallCount + 1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like this field isn't being checked in the tests. I assume you want to check it is 0.

assert.Equal(t, expected, authConfigs)
}

func TestGetAllCredentialsCredStoreAndCredHelper(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this one test might cover all the behaviour, but I guess it doesn't hurt to have the other ones. They should be pretty fast.

GetAllCallCount int
EraseCalls []string
GetCalls []string
StoreCalls []string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These Calls fields are also unused. They can be removed.

@dnephin
Copy link
Contributor

dnephin commented Jan 30, 2018

@thaJeztah do you know who is familiar with the credential helpers and could help review this?

@dekkagaijin
Copy link
Contributor Author

Done.
@dnephin I probably have some of the most context on the credHelpers in particular, otherwise one of the people from the original PR might be of help: moby/moby#25851

@thaJeztah
Copy link
Member

ping @n4ss PTAL

assert.Equal(t, 0, testCredHelper.(*mockNativeStore).GetAllCallCount)
}

func TestGetAllCredentialsCredStoreAndCredHelper(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this testing anything that isn't already covered by TestGetAllCredentialsCredHelperOverridesDefaultStore ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It tests that values from both are returned, if they don't conflict, rather than just one of the other. TestGetAllCredentialsCredHelperOverridesDefaultStore tests for the conflicting case.

Password: "cred_helper_pass",
}

testCredHelper := NewMockNativeStore(map[string]types.AuthConfig{testServerAddress: expectedCredHelperAuth})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think my previous comment wasn't clear. This map[string]types.AuthConfig should contain more than a single item. It should have extra items that you don't expect to get returned. Otherwise the implementation could return everything (the behaviour you're trying to fix) and the test would still pass.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, roger.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

defaultStore := configFile.GetCredentialsStore("")
newAuths, err := defaultStore.GetAll()
if err != nil {
return nil, err
}
addAll(newAuths)

// Auth configs from a registry-specific helper should override those from the default store.
for serverAddress := range configFile.CredentialHelpers {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: serverAdress is a bit too vague as a var name. Can we keep registry or registryAddr (same in the tests)?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM besides this

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

registryHostname? Done.

Copy link
Contributor

@dnephin dnephin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A test table, or extracting some of the common parts into setup functions might help reduce the duplication in the tests, but I think it will do as-is.

testCredHelper := NewMockNativeStore(map[string]types.AuthConfig{testServerAddress: expectedCredHelperAuth})
testCredsStore := NewMockNativeStore(map[string]types.AuthConfig{testServerAddress: unexpectedCredStoreAuth})

newNativeStore = func(configFile *ConfigFile, helperSuffix string) credentials.Store {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess there should be a defer to restore this to the original value when the test exits.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Contributor

@dnephin dnephin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@dekkagaijin
Copy link
Contributor Author

Gentle ping :)

@thaJeztah
Copy link
Member

ping @n4ss could you have another look

To reviewers: don't merge yet, as this may need some squashing once review is complete 🤗

@n4ss
Copy link
Contributor

n4ss commented Feb 6, 2018

@thaJeztah already reviewed & LGTM'd in a comment that got nested, sorry #840 (comment)

…lpers.

Signed-off-by: Jake Sanders <jsand@google.com>
@dekkagaijin
Copy link
Contributor Author

squished

@dekkagaijin
Copy link
Contributor Author

Bump <3

Signed-off-by: Jake Sanders <jsand@google.com>
@dekkagaijin
Copy link
Contributor Author

Added a fix for a small style nit, should let Jenkins and Codecov execute properly again as well.

@dekkagaijin
Copy link
Contributor Author

ping :)

Copy link
Collaborator

@vdemeester vdemeester left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🐯

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants