Return-Path: X-Original-To: apmail-brooklyn-dev-archive@minotaur.apache.org Delivered-To: apmail-brooklyn-dev-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 43E7711D96 for ; Thu, 26 Jun 2014 10:21:41 +0000 (UTC) Received: (qmail 1632 invoked by uid 500); 26 Jun 2014 10:21:41 -0000 Delivered-To: apmail-brooklyn-dev-archive@brooklyn.apache.org Received: (qmail 1600 invoked by uid 500); 26 Jun 2014 10:21:41 -0000 Mailing-List: contact dev-help@brooklyn.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@brooklyn.incubator.apache.org Delivered-To: mailing list dev@brooklyn.incubator.apache.org Received: (qmail 1589 invoked by uid 99); 26 Jun 2014 10:21:40 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 26 Jun 2014 10:21:40 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED,T_RP_MATCHES_RCVD X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO mail.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with SMTP; Thu, 26 Jun 2014 10:21:40 +0000 Received: (qmail 239 invoked by uid 99); 26 Jun 2014 10:21:14 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 26 Jun 2014 10:21:14 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id B3192834B29; Thu, 26 Jun 2014 10:21:14 +0000 (UTC) From: aledsage To: dev@brooklyn.incubator.apache.org Reply-To: dev@brooklyn.incubator.apache.org References: In-Reply-To: Subject: [GitHub] incubator-brooklyn pull request: fixes the "RetryOnRenew" lease-re... Content-Type: text/plain Message-Id: <20140626102114.B3192834B29@tyr.zones.apache.org> Date: Thu, 26 Jun 2014 10:21:14 +0000 (UTC) X-Virus-Checked: Checked by ClamAV on apache.org Github user aledsage commented on a diff in the pull request: https://github.com/apache/incubator-brooklyn/pull/19#discussion_r14233615 --- Diff: locations/jclouds/src/test/java/brooklyn/entity/rebind/persister/jclouds/BlobStoreExpiryTest.java --- @@ -0,0 +1,195 @@ +package brooklyn.entity.rebind.persister.jclouds; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.openstack.reference.AuthHeaders.URL_SUFFIX; + +import java.io.IOException; +import java.net.URI; +import java.util.List; +import java.util.Map.Entry; + +import org.apache.http.client.HttpClient; +import org.jclouds.blobstore.BlobStoreContext; +import org.jclouds.blobstore.domain.PageSet; +import org.jclouds.blobstore.domain.StorageMetadata; +import org.jclouds.domain.Credentials; +import org.jclouds.openstack.domain.AuthenticationResponse; +import org.jclouds.openstack.handlers.RetryOnRenew; +import org.jclouds.openstack.reference.AuthHeaders; +import org.junit.Assert; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import brooklyn.config.BrooklynProperties; +import brooklyn.entity.basic.Entities; +import brooklyn.location.basic.LocationConfigKeys; +import brooklyn.location.cloud.CloudLocationConfig; +import brooklyn.location.jclouds.JcloudsLocation; +import brooklyn.location.jclouds.JcloudsUtil; +import brooklyn.management.ManagementContext; +import brooklyn.test.entity.LocalManagementContextForTests; +import brooklyn.util.collections.MutableMap; +import brooklyn.util.http.HttpTool; +import brooklyn.util.http.HttpToolResponse; +import brooklyn.util.text.Identifiers; +import brooklyn.util.time.Duration; +import brooklyn.util.time.Time; + +import com.google.common.base.Preconditions; +import com.google.common.cache.LoadingCache; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMap.Builder; +import com.google.inject.Inject; +import com.google.inject.Module; + +@Test(groups="Integration") +public class BlobStoreExpiryTest { + + private static final Logger log = LoggerFactory.getLogger(BlobStoreExpiryTest.class); + + /** + * Integration tests as written require a location defined as follows: + * + * + * brooklyn.location.named.brooklyn-jclouds-objstore-test-1==jclouds:swift:https://ams01.objectstorage.softlayer.net/auth/v1.0 + * brooklyn.location.named.brooklyn-jclouds-objstore-test-1.identity=IBMOS1234-5:yourname + * brooklyn.location.named.brooklyn-jclouds-objstore-test-1.credential=0123abcd....... + * + */ + + public static final String PERSIST_TO_OBJECT_STORE_FOR_TEST_SPEC = BlobStoreTest.PERSIST_TO_OBJECT_STORE_FOR_TEST_SPEC; + public static final String CONTAINER_PREFIX = "brooklyn-persistence-test"; + private String locationSpec = PERSIST_TO_OBJECT_STORE_FOR_TEST_SPEC; + + private JcloudsLocation location; + private BlobStoreContext context; + + private ManagementContext mgmt; + private String testContainerName; + + Module myAuth; + private String identity; + private String credential; + private String provider; + private String endpoint; + + public synchronized BlobStoreContext getBlobStoreContext(boolean applyFix) { + if (context==null) { + if (location==null) { + Preconditions.checkNotNull(locationSpec, "locationSpec required for remote object store when location is null"); + Preconditions.checkNotNull(mgmt, "mgmt required for remote object store when location is null"); + location = (JcloudsLocation) mgmt.getLocationRegistry().resolve(locationSpec); + } + + identity = checkNotNull(location.getConfig(LocationConfigKeys.ACCESS_IDENTITY), "identity must not be null"); + credential = checkNotNull(location.getConfig(LocationConfigKeys.ACCESS_CREDENTIAL), "credential must not be null"); + provider = checkNotNull(location.getConfig(LocationConfigKeys.CLOUD_PROVIDER), "provider must not be null"); + endpoint = location.getConfig(CloudLocationConfig.CLOUD_ENDPOINT); + + context = JcloudsUtil.newBlobstoreContext(provider, endpoint, identity, credential, applyFix); + } + return context; + } + + @BeforeMethod(alwaysRun=true) + public void setup() { + testContainerName = CONTAINER_PREFIX+"-"+Identifiers.makeRandomId(8); + mgmt = new LocalManagementContextForTests(BrooklynProperties.Factory.newDefault()); + } + + @AfterMethod(alwaysRun=true) + public void teardown() { + Entities.destroyAll(mgmt); + if (context!=null) context.close(); + context = null; + } + + public void testRenewAuthFailsInSoftlayer() throws IOException { + doTestRenewAuth(false); + } + + public void testRenewAuthSucceedsWithOurOverride() throws IOException { + doTestRenewAuth(true); + } + + protected void doTestRenewAuth(boolean applyFix) throws IOException { + getBlobStoreContext(applyFix); + + injectShortLivedTokenForSoftlayerAmsterdam(); + + context.getBlobStore().createContainerInLocation(null, testContainerName); + + assertContainerFound(); + + log.info("created container, now sleeping for expiration"); + + Time.sleep(Duration.TEN_SECONDS); + + if (!applyFix) { + // with the fix not applied, we have to invalidate the cache manually + try { + assertContainerFound(); + Assert.fail("should fail as long as "+RetryOnRenew.class+" is not working"); + } catch (Exception e) { + log.info("failed, as expected: "+e); + } + getAuthCache().invalidateAll(); + log.info("invalidated, should now succeed"); + } + + assertContainerFound(); + + context.getBlobStore().deleteContainer(testContainerName); + } + + private void assertContainerFound() { + PageSet ps = context.getBlobStore().list(); + BlobStoreTest.assertHasItemNamed(ps, testContainerName); + } + + private void injectShortLivedTokenForSoftlayerAmsterdam() { + HttpToolResponse tokenHttpResponse1 = requestTokenWithExplicitLifetime("https://ams01.objectstorage.softlayer.net/auth/v1.0/v1.0", "ams01.objectstorage.softlayer.net", + identity, credential, Duration.FIVE_SECONDS); + + Builder servicesMapBuilder = ImmutableMap.builder(); + for (Entry> entry : tokenHttpResponse1.getHeaderLists().entrySet()) { + if (entry.getKey().toLowerCase().endsWith(URL_SUFFIX.toLowerCase())) + servicesMapBuilder.put(entry.getKey(), URI.create(entry.getValue().iterator().next())); + } + AuthenticationResponse authResponse = new AuthenticationResponse(tokenHttpResponse1.getHeaderLists().get(AuthHeaders.AUTH_TOKEN).get(0), servicesMapBuilder.build()); + + getAuthCache().put(new Credentials(identity, credential), authResponse); + } + + private LoadingCache getAuthCache() { + return context.utils().injector().getInstance(CachePeeker.class).authenticationResponseCache; + } + + public static class CachePeeker { + private final LoadingCache authenticationResponseCache; + + @Inject + protected CachePeeker(LoadingCache authenticationResponseCache) { + this.authenticationResponseCache = authenticationResponseCache; + } + } + + public static HttpToolResponse requestTokenWithExplicitLifetime(String url, String host, String user, String key, Duration expiration) { + HttpClient client = HttpTool.httpClientBuilder().build(); + HttpToolResponse response = HttpTool.httpGet(client, URI.create(url), MutableMap.of() + .add(AuthHeaders.AUTH_USER, user) + .add(AuthHeaders.AUTH_KEY, key) + .add("Host", host) + .add("X-Auth-New-Token", ""+true) + .add("X-Auth-Token-Lifetime", ""+expiration.toSeconds()) --- End diff -- Nice testing! Should this be a `Live` test rather than an `Integration` test though? --- If your project is set up for it, you can reply to this email and have your reply appear on GitHub as well. If your project does not have this feature enabled and wishes so, or if the feature is enabled but not working, please contact infrastructure at infrastructure@apache.org or file a JIRA ticket with INFRA. ---