mirror of https://github.com/apache/jclouds.git
Issue 883:Allow login credentials by osfamily to be specified per-provider
This commit is contained in:
parent
774c4412aa
commit
2ae849dd94
|
@ -26,6 +26,7 @@ import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.compute.domain.OsFamily;
|
||||||
import org.jclouds.compute.strategy.impl.ReturnCredentialsBoundToImage;
|
import org.jclouds.compute.strategy.impl.ReturnCredentialsBoundToImage;
|
||||||
import org.jclouds.domain.Credentials;
|
import org.jclouds.domain.Credentials;
|
||||||
import org.jclouds.domain.LoginCredentials;
|
import org.jclouds.domain.LoginCredentials;
|
||||||
|
@ -41,13 +42,13 @@ import com.google.common.collect.ImmutableMap;
|
||||||
@Singleton
|
@Singleton
|
||||||
public class EC2PopulateDefaultLoginCredentialsForImageStrategy extends ReturnCredentialsBoundToImage {
|
public class EC2PopulateDefaultLoginCredentialsForImageStrategy extends ReturnCredentialsBoundToImage {
|
||||||
public EC2PopulateDefaultLoginCredentialsForImageStrategy() {
|
public EC2PopulateDefaultLoginCredentialsForImageStrategy() {
|
||||||
this(null, ImmutableMap.<String, Credentials> of());
|
this(null, ImmutableMap.<String, Credentials> of(), ImmutableMap.<OsFamily, LoginCredentials>of());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public EC2PopulateDefaultLoginCredentialsForImageStrategy(@Nullable @Named("image") LoginCredentials creds,
|
public EC2PopulateDefaultLoginCredentialsForImageStrategy(@Nullable @Named("image") LoginCredentials creds,
|
||||||
Map<String, Credentials> credentialStore) {
|
Map<String, Credentials> credentialStore, Map<OsFamily, LoginCredentials> osFamilyToCredentials) {
|
||||||
super(creds, credentialStore);
|
super(creds, credentialStore, osFamilyToCredentials);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -30,6 +30,7 @@ import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.compute.domain.OsFamily;
|
||||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||||
import org.jclouds.compute.strategy.impl.ReturnCredentialsBoundToImage;
|
import org.jclouds.compute.strategy.impl.ReturnCredentialsBoundToImage;
|
||||||
import org.jclouds.domain.Credentials;
|
import org.jclouds.domain.Credentials;
|
||||||
|
@ -45,8 +46,8 @@ import org.jclouds.trmk.vcloud_0_8.domain.VAppTemplate;
|
||||||
public class ParseVAppTemplateDescriptionToGetDefaultLoginCredentials extends ReturnCredentialsBoundToImage {
|
public class ParseVAppTemplateDescriptionToGetDefaultLoginCredentials extends ReturnCredentialsBoundToImage {
|
||||||
@Inject
|
@Inject
|
||||||
public ParseVAppTemplateDescriptionToGetDefaultLoginCredentials(@Nullable @Named("image") LoginCredentials creds,
|
public ParseVAppTemplateDescriptionToGetDefaultLoginCredentials(@Nullable @Named("image") LoginCredentials creds,
|
||||||
Map<String, Credentials> credentialStore) {
|
Map<String, Credentials> credentialStore, Map<OsFamily, LoginCredentials> osFamilyToCredentials) {
|
||||||
super(creds, credentialStore);
|
super(creds, credentialStore, osFamilyToCredentials);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
|
|
|
@ -18,17 +18,18 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.trmk.vcloud_0_8.compute.strategy;
|
package org.jclouds.trmk.vcloud_0_8.compute.strategy;
|
||||||
|
|
||||||
|
import static org.easymock.EasyMock.createMock;
|
||||||
import static org.easymock.EasyMock.expect;
|
import static org.easymock.EasyMock.expect;
|
||||||
import static org.easymock.classextension.EasyMock.createMock;
|
import static org.easymock.EasyMock.replay;
|
||||||
import static org.easymock.classextension.EasyMock.replay;
|
import static org.easymock.EasyMock.verify;
|
||||||
import static org.easymock.classextension.EasyMock.verify;
|
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import org.jclouds.compute.domain.OsFamily;
|
||||||
import org.jclouds.domain.Credentials;
|
import org.jclouds.domain.Credentials;
|
||||||
import org.jclouds.trmk.vcloud_0_8.compute.strategy.ParseVAppTemplateDescriptionToGetDefaultLoginCredentials;
|
import org.jclouds.domain.LoginCredentials;
|
||||||
import org.jclouds.trmk.vcloud_0_8.domain.VAppTemplate;
|
import org.jclouds.trmk.vcloud_0_8.domain.VAppTemplate;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
@ -49,7 +50,7 @@ public class PopulateDefaultLoginCredentialsForVAppTemplateTest {
|
||||||
expect(template.getDescription()).andReturn(description).atLeastOnce();
|
expect(template.getDescription()).andReturn(description).atLeastOnce();
|
||||||
replay(template);
|
replay(template);
|
||||||
ParseVAppTemplateDescriptionToGetDefaultLoginCredentials converter = new ParseVAppTemplateDescriptionToGetDefaultLoginCredentials(
|
ParseVAppTemplateDescriptionToGetDefaultLoginCredentials converter = new ParseVAppTemplateDescriptionToGetDefaultLoginCredentials(
|
||||||
null, ImmutableMap.<String, Credentials> of());
|
null, ImmutableMap.<String, Credentials> of(), ImmutableMap.<OsFamily, LoginCredentials> of());
|
||||||
Credentials creds = converter.execute(template);
|
Credentials creds = converter.execute(template);
|
||||||
assertEquals(creds.identity, "vcloud");
|
assertEquals(creds.identity, "vcloud");
|
||||||
assertEquals(creds.credential, "$Ep455l0ud!2");
|
assertEquals(creds.credential, "$Ep455l0ud!2");
|
||||||
|
@ -64,7 +65,7 @@ public class PopulateDefaultLoginCredentialsForVAppTemplateTest {
|
||||||
expect(template.getDescription()).andReturn(description).atLeastOnce();
|
expect(template.getDescription()).andReturn(description).atLeastOnce();
|
||||||
replay(template);
|
replay(template);
|
||||||
ParseVAppTemplateDescriptionToGetDefaultLoginCredentials converter = new ParseVAppTemplateDescriptionToGetDefaultLoginCredentials(
|
ParseVAppTemplateDescriptionToGetDefaultLoginCredentials converter = new ParseVAppTemplateDescriptionToGetDefaultLoginCredentials(
|
||||||
null, ImmutableMap.<String, Credentials> of());
|
null, ImmutableMap.<String, Credentials> of(), ImmutableMap.<OsFamily, LoginCredentials> of());
|
||||||
Credentials creds = converter.execute(template);
|
Credentials creds = converter.execute(template);
|
||||||
assertEquals(creds.identity, "ecloud");
|
assertEquals(creds.identity, "ecloud");
|
||||||
assertEquals(creds.credential, "$Ep455l0ud!2");
|
assertEquals(creds.credential, "$Ep455l0ud!2");
|
||||||
|
@ -79,7 +80,7 @@ public class PopulateDefaultLoginCredentialsForVAppTemplateTest {
|
||||||
expect(template.getDescription()).andReturn(description).atLeastOnce();
|
expect(template.getDescription()).andReturn(description).atLeastOnce();
|
||||||
replay(template);
|
replay(template);
|
||||||
ParseVAppTemplateDescriptionToGetDefaultLoginCredentials converter = new ParseVAppTemplateDescriptionToGetDefaultLoginCredentials(
|
ParseVAppTemplateDescriptionToGetDefaultLoginCredentials converter = new ParseVAppTemplateDescriptionToGetDefaultLoginCredentials(
|
||||||
null, ImmutableMap.<String, Credentials> of());
|
null, ImmutableMap.<String, Credentials> of(), ImmutableMap.<OsFamily, LoginCredentials> of());
|
||||||
Credentials creds = converter.execute(template);
|
Credentials creds = converter.execute(template);
|
||||||
assertEquals(creds.identity, "vpncubed");
|
assertEquals(creds.identity, "vpncubed");
|
||||||
assertEquals(creds.credential, "vpncubed");
|
assertEquals(creds.credential, "vpncubed");
|
||||||
|
@ -94,7 +95,7 @@ public class PopulateDefaultLoginCredentialsForVAppTemplateTest {
|
||||||
expect(template.getDescription()).andReturn(description).atLeastOnce();
|
expect(template.getDescription()).andReturn(description).atLeastOnce();
|
||||||
replay(template);
|
replay(template);
|
||||||
ParseVAppTemplateDescriptionToGetDefaultLoginCredentials converter = new ParseVAppTemplateDescriptionToGetDefaultLoginCredentials(
|
ParseVAppTemplateDescriptionToGetDefaultLoginCredentials converter = new ParseVAppTemplateDescriptionToGetDefaultLoginCredentials(
|
||||||
null, ImmutableMap.<String, Credentials> of());
|
null, ImmutableMap.<String, Credentials> of(), ImmutableMap.<OsFamily, LoginCredentials> of());
|
||||||
Credentials creds = converter.execute(template);
|
Credentials creds = converter.execute(template);
|
||||||
assertEquals(creds.identity, "ecloud");
|
assertEquals(creds.identity, "ecloud");
|
||||||
assertEquals(creds.credential, "TmrkCl0ud1s#1!");
|
assertEquals(creds.credential, "TmrkCl0ud1s#1!");
|
||||||
|
@ -109,7 +110,7 @@ public class PopulateDefaultLoginCredentialsForVAppTemplateTest {
|
||||||
expect(template.getDescription()).andReturn(description).atLeastOnce();
|
expect(template.getDescription()).andReturn(description).atLeastOnce();
|
||||||
replay(template);
|
replay(template);
|
||||||
ParseVAppTemplateDescriptionToGetDefaultLoginCredentials converter = new ParseVAppTemplateDescriptionToGetDefaultLoginCredentials(
|
ParseVAppTemplateDescriptionToGetDefaultLoginCredentials converter = new ParseVAppTemplateDescriptionToGetDefaultLoginCredentials(
|
||||||
null, ImmutableMap.<String, Credentials> of());
|
null, ImmutableMap.<String, Credentials> of(), ImmutableMap.<OsFamily, LoginCredentials> of());
|
||||||
Credentials creds = converter.execute(template);
|
Credentials creds = converter.execute(template);
|
||||||
assertEquals(creds.identity, "Administrator");
|
assertEquals(creds.identity, "Administrator");
|
||||||
assertEquals(creds.credential, null);
|
assertEquals(creds.credential, null);
|
||||||
|
|
|
@ -63,6 +63,7 @@ import org.jclouds.ssh.SshClient;
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
import com.google.common.base.Suppliers;
|
import com.google.common.base.Suppliers;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
@ -183,7 +184,13 @@ public abstract class BaseComputeServiceContextModule extends AbstractModule {
|
||||||
protected TemplateBuilder provideTemplate(Injector injector, TemplateBuilder template) {
|
protected TemplateBuilder provideTemplate(Injector injector, TemplateBuilder template) {
|
||||||
return template.osFamily(UBUNTU).osVersionMatches("1[012].[01][04]").os64Bit(true);
|
return template.osFamily(UBUNTU).osVersionMatches("1[012].[01][04]").os64Bit(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
protected Map<OsFamily, LoginCredentials> osFamilyToCredentials(Injector injector) {
|
||||||
|
return ImmutableMap.of(OsFamily.WINDOWS, LoginCredentials.builder().user("Administrator").build());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default options if none are provided.
|
* The default options if none are provided.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -40,13 +40,15 @@ import org.jclouds.javax.annotation.Nullable;
|
||||||
public class ReturnCredentialsBoundToImage implements PopulateDefaultLoginCredentialsForImageStrategy {
|
public class ReturnCredentialsBoundToImage implements PopulateDefaultLoginCredentialsForImageStrategy {
|
||||||
|
|
||||||
protected final LoginCredentials creds;
|
protected final LoginCredentials creds;
|
||||||
protected Map<String, Credentials> credentialStore;
|
protected final Map<String, Credentials> credentialStore;
|
||||||
|
protected final Map<OsFamily, LoginCredentials> osFamilyToCredentials;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public ReturnCredentialsBoundToImage(@Nullable @Named("image") LoginCredentials creds,
|
public ReturnCredentialsBoundToImage(@Nullable @Named("image") LoginCredentials creds,
|
||||||
Map<String, Credentials> credentialStore) {
|
Map<String, Credentials> credentialStore, Map<OsFamily, LoginCredentials> osFamilyToCredentials) {
|
||||||
this.creds = creds;
|
this.creds = creds;
|
||||||
this.credentialStore = credentialStore;
|
this.credentialStore = credentialStore;
|
||||||
|
this.osFamilyToCredentials = osFamilyToCredentials;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -58,8 +60,9 @@ public class ReturnCredentialsBoundToImage implements PopulateDefaultLoginCreden
|
||||||
Image image = Image.class.cast(resourceToAuthenticate);
|
Image image = Image.class.cast(resourceToAuthenticate);
|
||||||
if (credentialStore.containsKey("image#" + image.getId()))
|
if (credentialStore.containsKey("image#" + image.getId()))
|
||||||
return LoginCredentials.fromCredentials(credentialStore.get("image#" + image.getId()));
|
return LoginCredentials.fromCredentials(credentialStore.get("image#" + image.getId()));
|
||||||
if (image.getOperatingSystem() != null && OsFamily.WINDOWS.equals(image.getOperatingSystem().getFamily())) {
|
if (image.getOperatingSystem() != null && image.getOperatingSystem().getFamily() != null
|
||||||
return LoginCredentials.builder().user("Administrator").build();
|
&& osFamilyToCredentials.containsKey(image.getOperatingSystem().getFamily())) {
|
||||||
|
return osFamilyToCredentials.get(image.getOperatingSystem().getFamily());
|
||||||
} else {
|
} else {
|
||||||
return LoginCredentials.builder().user("root").build();
|
return LoginCredentials.builder().user("root").build();
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,8 +45,8 @@ public class ReturnCredentialsBoundToImageTest {
|
||||||
replay(image);
|
replay(image);
|
||||||
|
|
||||||
LoginCredentials creds = new LoginCredentials("ubuntu", "foo", null, false);
|
LoginCredentials creds = new LoginCredentials("ubuntu", "foo", null, false);
|
||||||
assertEquals(new ReturnCredentialsBoundToImage(creds, ImmutableMap.<String, Credentials> of()).execute(image),
|
assertEquals(new ReturnCredentialsBoundToImage(creds, ImmutableMap.<String, Credentials> of(), ImmutableMap
|
||||||
creds);
|
.<OsFamily, LoginCredentials> of()).execute(image), creds);
|
||||||
|
|
||||||
verify(image);
|
verify(image);
|
||||||
|
|
||||||
|
@ -58,14 +58,14 @@ public class ReturnCredentialsBoundToImageTest {
|
||||||
replay(image);
|
replay(image);
|
||||||
|
|
||||||
LoginCredentials creds = new LoginCredentials("ubuntu", "foo", null, false);
|
LoginCredentials creds = new LoginCredentials("ubuntu", "foo", null, false);
|
||||||
assertEquals(new ReturnCredentialsBoundToImage(null, ImmutableMap.<String, Credentials> of("image#1",creds)).execute(image),
|
assertEquals(new ReturnCredentialsBoundToImage(null, ImmutableMap.<String, Credentials> of("image#1", creds),
|
||||||
creds);
|
ImmutableMap.<OsFamily, LoginCredentials> of()).execute(image), creds);
|
||||||
|
|
||||||
verify(image);
|
verify(image);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testReturnAdministratorOnWindows() {
|
public void testReturnLoginCredentialAssociatedToOsFamily() {
|
||||||
Image image = createMock(Image.class);
|
Image image = createMock(Image.class);
|
||||||
expect(image.getId()).andReturn("1");
|
expect(image.getId()).andReturn("1");
|
||||||
expect(image.getOperatingSystem()).andReturn(
|
expect(image.getOperatingSystem()).andReturn(
|
||||||
|
@ -73,7 +73,8 @@ public class ReturnCredentialsBoundToImageTest {
|
||||||
replay(image);
|
replay(image);
|
||||||
|
|
||||||
Credentials creds = new Credentials("Administrator", null);
|
Credentials creds = new Credentials("Administrator", null);
|
||||||
assertEquals(new ReturnCredentialsBoundToImage(null, ImmutableMap.<String, Credentials> of()).execute(image), creds);
|
assertEquals(new ReturnCredentialsBoundToImage(null, ImmutableMap.<String, Credentials> of(), ImmutableMap.of(
|
||||||
|
OsFamily.WINDOWS, LoginCredentials.builder().user("Administrator").build())).execute(image), creds);
|
||||||
|
|
||||||
verify(image);
|
verify(image);
|
||||||
|
|
||||||
|
@ -87,7 +88,8 @@ public class ReturnCredentialsBoundToImageTest {
|
||||||
replay(image);
|
replay(image);
|
||||||
|
|
||||||
Credentials creds = new Credentials("root", null);
|
Credentials creds = new Credentials("root", null);
|
||||||
assertEquals(new ReturnCredentialsBoundToImage(null, ImmutableMap.<String, Credentials> of()).execute(image), creds);
|
assertEquals(new ReturnCredentialsBoundToImage(null, ImmutableMap.<String, Credentials> of(), ImmutableMap
|
||||||
|
.<OsFamily, LoginCredentials> of()).execute(image), creds);
|
||||||
|
|
||||||
verify(image);
|
verify(image);
|
||||||
|
|
||||||
|
|
|
@ -74,7 +74,8 @@ public class HPCloudComputeTemplateBuilderLiveTest extends BaseTemplateBuilderLi
|
||||||
assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "11.10");
|
assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "11.10");
|
||||||
assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
|
assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
|
||||||
assertEquals(defaultTemplate.getImage().getName(), "Ubuntu Oneiric 11.10 Server 64-bit 20111212");
|
assertEquals(defaultTemplate.getImage().getName(), "Ubuntu Oneiric 11.10 Server 64-bit 20111212");
|
||||||
assertEquals(defaultTemplate.getLocation().getId(), "az-1.region-a.geo-1");
|
assertEquals(defaultTemplate.getImage().getDefaultCredentials().getUser(), "ubuntu");
|
||||||
|
assertEquals(defaultTemplate.getLocation().getId(), "az-2.region-a.geo-1");
|
||||||
assertEquals(defaultTemplate.getOptions().as(NovaTemplateOptions.class).shouldAutoAssignFloatingIp(), true);
|
assertEquals(defaultTemplate.getOptions().as(NovaTemplateOptions.class).shouldAutoAssignFloatingIp(), true);
|
||||||
assertEquals(getCores(defaultTemplate.getHardware()), 1.0d);
|
assertEquals(getCores(defaultTemplate.getHardware()), 1.0d);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,9 +35,11 @@ import org.jclouds.compute.domain.Hardware;
|
||||||
import org.jclouds.compute.domain.Image;
|
import org.jclouds.compute.domain.Image;
|
||||||
import org.jclouds.compute.domain.NodeMetadata;
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
import org.jclouds.compute.domain.OperatingSystem;
|
import org.jclouds.compute.domain.OperatingSystem;
|
||||||
|
import org.jclouds.compute.domain.OsFamily;
|
||||||
import org.jclouds.compute.options.TemplateOptions;
|
import org.jclouds.compute.options.TemplateOptions;
|
||||||
import org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet;
|
import org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet;
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
|
import org.jclouds.domain.LoginCredentials;
|
||||||
import org.jclouds.functions.IdentityFunction;
|
import org.jclouds.functions.IdentityFunction;
|
||||||
import org.jclouds.openstack.nova.v1_1.NovaAsyncClient;
|
import org.jclouds.openstack.nova.v1_1.NovaAsyncClient;
|
||||||
import org.jclouds.openstack.nova.v1_1.NovaClient;
|
import org.jclouds.openstack.nova.v1_1.NovaClient;
|
||||||
|
@ -68,6 +70,7 @@ import com.google.common.base.Suppliers;
|
||||||
import com.google.common.cache.CacheBuilder;
|
import com.google.common.cache.CacheBuilder;
|
||||||
import com.google.common.cache.CacheLoader;
|
import com.google.common.cache.CacheLoader;
|
||||||
import com.google.common.cache.LoadingCache;
|
import com.google.common.cache.LoadingCache;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
import com.google.inject.Injector;
|
import com.google.inject.Injector;
|
||||||
|
@ -159,6 +162,12 @@ public class NovaComputeServiceContextModule
|
||||||
CacheLoader<ZoneAndName, SecurityGroupInZone> in) {
|
CacheLoader<ZoneAndName, SecurityGroupInZone> in) {
|
||||||
return CacheBuilder.newBuilder().build(in);
|
return CacheBuilder.newBuilder().build(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Map<OsFamily, LoginCredentials> osFamilyToCredentials(Injector injector) {
|
||||||
|
return ImmutableMap.of(OsFamily.WINDOWS, LoginCredentials.builder().user("Administrator").build(),
|
||||||
|
OsFamily.UBUNTU, LoginCredentials.builder().user("ubuntu").build());
|
||||||
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
|
|
Loading…
Reference in New Issue