-
Notifications
You must be signed in to change notification settings - Fork 550
Conversation
one thing we decided to punt on for the moment is customizing the GCR RegistryAuthSupplier to be able to do something like |
c5c2236
to
8fea305
Compare
import com.spotify.docker.client.messages.RegistryConfigs; | ||
|
||
/** | ||
* Wraps a RegistryAuth with the RegisrtyAuthSupplier interface. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed, thanks
👍 |
adf8d21
to
b6d531d
Compare
Codecov Report
@@ Coverage Diff @@
## master #759 +/- ##
============================================
+ Coverage 65.56% 65.89% +0.32%
- Complexity 656 672 +16
============================================
Files 153 158 +5
Lines 2878 2926 +48
Branches 335 335
============================================
+ Hits 1887 1928 +41
- Misses 844 850 +6
- Partials 147 148 +1 |
2f67e16
to
b43336d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't take that close of a look at tests though.
} | ||
|
||
return request( | ||
GET, | ||
InputStream.class, | ||
resource, | ||
resource.request(APPLICATION_JSON_TYPE).header("X-Registry-Auth", authHeader(registryAuth)) | ||
resource.request(APPLICATION_JSON_TYPE).header("X-Registry-Auth", authHeader( | ||
registryAuthSupplier.authFor(images[0]))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this endpoint need auth at all? Docs don't mention it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure, but the existing code has it.
public Builder registryAuth(final RegistryAuth registryAuth) { | ||
if (this.registryAuthSupplier != null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will we keep this logic or remove registryAuth()
at some point?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to remove all the deprecated methods in a future release - see what I added to Changelog
new DockerConfigReader().defaultConfigPath()); | ||
} | ||
|
||
public GoogleContainerRegistryAuthSupplier(DockerConfigReader dockerCfgReader, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: can we put each param on a new line?
private static final ObjectMapper MAPPER = ObjectMapperProvider.objectMapper(); | ||
|
||
/** Returns all RegistryConfig instances from the configuration file. */ | ||
public RegistryConfigs fromConfig(Path configPath) throws IOException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not make these all static methods? Then you remove a call to the constructor at call sites.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this was done to make it easy to mock it
|
||
private static final String DEFAULT_REGISTRY = "https://index.docker.io/v1/"; | ||
private static final String DUMMY_EMAIL = "[email protected]"; | ||
|
||
@SuppressWarnings("FieldCanBeLocal") | ||
private static final ObjectMapper MAPPER = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unused
public abstract ImmutableMap<String, RegistryConfig> configs(); | ||
|
||
@AutoValue | ||
public abstract static class RegistryConfig { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice. Why did I add these in the first place?!
Adds support for RegistryAuthSupplier. Client code can consume this using DefaultDockerClient builder. Provides support for authenticating against GCR to allow pushes/pulls from GCR.
the Build method in the Docker Remote API allows for passing *all* of the RegistryAuth structs that the client knows about, this updates the RegistryAuthSupplier interface to match that.
use the same method for parsing the config file in both code paths
and bump library version to 8.6.0 as significant new functionality is added/deprecated here
testAuth and testBadAuth is failing on Docker 1.9 and 1.10 because RegistryAuth.email is not set when we send it to the daemon
652ba48
to
9d65790
Compare
} | ||
|
||
public Builder registryAuthSupplier(final RegistryAuthSupplier registryAuthSupplier) { | ||
if (this.registryAuthSupplier != null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this check if(this.registryAuth != null)
? Right now this would only get triggered if the user called builder().registryAuthSupplier(registryAuthSupplier).registryAuthSupplier(registryAuthSupplier)
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Builder.registryAuth(RegistryAuth)
is setting this.registryAuthSupplier
to a non-null value
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would remove the registryAuth
field from the Builder altogether but there is a registryAuth()
getter for some reason
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
9d65790
to
073ad23
Compare
try { | ||
String registryName = "https://" + imageName.split("/")[0]; | ||
refresher.refresh(); | ||
return reader.fromConfig(configPath, registryName); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wanted to pull busybox:latest
and push to gcr.io/myproject/busybox:latest
and realized I have to use two DockerClient
s to do this or implement my own RegistryAuthSupplier
that checks if the image name starts with gcr.io/
.
final DefaultDockerClient docker = DefaultDockerClient.fromEnv()
.registryAuthSupplier(new GoogleContainerRegistryAuthSupplier())
.build();
docker.pull("busybox:latest");
docker.tag("busybox:latest", "gcr.io/myproject/busybox:latest");
docker.push("gcr.io/myproject/busybox:latest");
will throw
java.lang.IllegalArgumentException: serverAddress=https://busybox:latest does not appear in config file at /Users/dxia/.docker/config.json
at com.spotify.docker.client.DockerConfigReader.parseDockerConfig(DockerConfigReader.java:81)
at com.spotify.docker.client.DockerConfigReader.fromConfig(DockerConfigReader.java:51)
at com.spotify.docker.client.gcr.GoogleContainerRegistryAuthSupplier.authFor(GoogleContainerRegistryAuthSupplier.java:58)
at com.spotify.docker.client.DefaultDockerClient.pull(DefaultDockerClient.java:1196)
at com.spotify.docker.client.DefaultDockerClient.pull(DefaultDockerClient.java:1190)
at com.spotify.gcpprojectcreator.gcloud.IamPolicyHandlerTest.foo(IamPolicyHandlerTest.java:160)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Is this intended?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, this is not intended.
I think this refactoring requires a few more changes before it is really complete and can be released. I wanted to merge what we have so far to avoid the PR growing gigantic. I'll fix this and I'm also close to being able to run this code locally in helios with GCR.
This completes #749 - David and I worked on this together in-person.
The new
RegistryAuthSupplier
interface replaces the existingRegistryAuth
support in DefaultDockerClient so that users can customize the authentication behavior much more closely. On each operation that requires authentication, DefaultDockerClient will invoke the appropriate method on the RegistryAuthSupplier instance, allowing the implementation to supply up-to-date authentication information/tokens.This change is inspired by our attempts to integrate with Google Container Registry, where
~/.docker/config.json
file contains short-lived access tokens that expire shortly after creation. This means that a long-lived DefaultDockerClient instance cannot store static RegistryAuth information from construction-time.Also included is an implementation of RegistryAuthSupplier that refreshes the access tokens supplied by
gcloud docker -a
prior to eachauthFor(..)
operation, as well as an implementation of RegistryAuthSupplier that returns static data.Closes #740.