@Override public InstanceAttribute getInstanceAttribute(String instanceId, String attributeName) { OperationStats ops = new OperationStats("es2InstanceStore", "getInstanceAttribute"); try { awsRateLimiter.acquire(); DescribeInstanceAttributeRequest request = new DescribeInstanceAttributeRequest() .withInstanceId(instanceId) .withAttribute(InstanceAttributeName.fromValue(attributeName)) .withSdkRequestTimeout(300 * 1000).withSdkClientExecutionTimeout(600 * 1000); DescribeInstanceAttributeResult result = defaultClient.describeInstanceAttribute(request); while (result != null) { ops.succeed(); return result.getInstanceAttribute(); } } catch (Exception ex) { ops.failed(); throw ex; } return null; }
@Override public Map<String, String> getUserData(String instanceId) throws Exception { Preconditions.checkNotNull(instanceId); awsRateLimiter.acquire(); OperationStats op = new OperationStats("ec2InstanceStore", "getUserData"); try { InstanceAttribute attribute = this.getInstanceAttribute(instanceId, "userData"); if (attribute != null) { String base64EncodedString = attribute.getUserData(); if (StringUtils.isNoneEmpty(base64EncodedString)) { Map<String, String> userData = Ec2InstanceStore.parseEc2UserData(base64EncodedString); op.succeed(); return userData; } } } catch (Exception ex) { op.failed(); throw ex; } op.succeed(); return new HashMap<>(); }
/** * Get EBS volumes attached to the specified virtual instance id. * * @return list of ebs volumes */ @VisibleForTesting List<Volume> getVolumes(String virtualInstanceId) { String ec2InstanceId = getOnlyElement( getEC2InstanceIdsByVirtualInstanceId( Collections.singletonList(virtualInstanceId) ).values() ); InstanceAttribute instanceAttribute = describeInstanceAttribute(ec2InstanceId, InstanceAttributeName.BlockDeviceMapping); List<InstanceBlockDeviceMapping> blockDeviceMappings = instanceAttribute.getBlockDeviceMappings(); List<String> volumeIds = Lists.newArrayList(); for (InstanceBlockDeviceMapping mapping : blockDeviceMappings) { volumeIds.add(mapping.getEbs().getVolumeId()); } DescribeVolumesResult volumeResults = client.describeVolumes( new DescribeVolumesRequest().withVolumeIds(volumeIds) ); return volumeResults.getVolumes(); }
@Test public void testBrokenYaml() throws Exception{ // a yaml list is not a valid taupage format. Map is required. final String yamlData = "- a\n- b\n- c\n"; when(amazonEC2ClientMock.describeInstanceAttribute(any())).thenReturn(new DescribeInstanceAttributeResult(). withInstanceAttribute(new InstanceAttribute() .withUserData(Base64.encodeAsString(yamlData.getBytes())))); final FetchTaupageYaml fetchTaupageYaml = new FetchTaupageYamlImpl(clientProviderMock); final Optional<TaupageYaml> result = fetchTaupageYaml.getTaupageYaml(INSTANCE_ID, ACCOUNT, REGION); assertThat(result).isEmpty(); verify(amazonEC2ClientMock).describeInstanceAttribute(any()); }
@Test public void testApplyWithTaupageAmi() throws Exception { when(ec2InstanceContextMock.isTaupageAmi()).thenReturn(Optional.of(true)); when(ec2InstanceContextMock.getInstanceId()).thenReturn(INSTANCE_ID); when(ec2InstanceContextMock.getClient(eq(AmazonEC2Client.class))).thenReturn(amazonEC2ClientMock); when(amazonEC2ClientMock.describeInstanceAttribute(any())).thenReturn(new DescribeInstanceAttributeResult(). withInstanceAttribute(new InstanceAttribute() .withUserData(Base64.encodeAsString("blub: fdsa".getBytes())))); final Optional<TaupageYaml> result = taupageYamlProvider.apply(ec2InstanceContextMock); assertThat(result).isPresent(); verify(ec2InstanceContextMock).isTaupageAmi(); verify(ec2InstanceContextMock).getInstanceId(); verify(ec2InstanceContextMock).getClient(eq(AmazonEC2Client.class)); verify(amazonEC2ClientMock).describeInstanceAttribute(any()); }
@Test public void testApplyWithVersionSimilarToNumber() throws Exception { when(ec2InstanceContextMock.isTaupageAmi()).thenReturn(Optional.of(true)); when(ec2InstanceContextMock.getInstanceId()).thenReturn(INSTANCE_ID); when(ec2InstanceContextMock.getClient(eq(AmazonEC2Client.class))).thenReturn(amazonEC2ClientMock); when(amazonEC2ClientMock.describeInstanceAttribute(any())).thenReturn(new DescribeInstanceAttributeResult(). withInstanceAttribute(new InstanceAttribute() .withUserData(Base64.encodeAsString("application_id: fdsa\napplication_version: 6478e18".getBytes())))); final Optional<TaupageYaml> result = taupageYamlProvider.apply(ec2InstanceContextMock); assertThat(result).isPresent(); assertThat(result.get().getApplicationId()).isEqualTo("fdsa"); assertThat(result.get().getApplicationVersion()).isEqualTo("6478e18"); verify(ec2InstanceContextMock).isTaupageAmi(); verify(ec2InstanceContextMock).getInstanceId(); verify(ec2InstanceContextMock).getClient(eq(AmazonEC2Client.class)); verify(amazonEC2ClientMock).describeInstanceAttribute(any()); }
@Test public void testApplyWithVersionSimilarToNumber1() throws Exception { when(ec2InstanceContextMock.isTaupageAmi()).thenReturn(Optional.of(true)); when(ec2InstanceContextMock.getInstanceId()).thenReturn(INSTANCE_ID); when(ec2InstanceContextMock.getClient(eq(AmazonEC2Client.class))).thenReturn(amazonEC2ClientMock); when(amazonEC2ClientMock.describeInstanceAttribute(any())).thenReturn(new DescribeInstanceAttributeResult(). withInstanceAttribute(new InstanceAttribute() .withUserData(Base64.encodeAsString("application_id: fdsa\napplication_version: '6478e18'".getBytes())))); final Optional<TaupageYaml> result = taupageYamlProvider.apply(ec2InstanceContextMock); assertThat(result).isPresent(); assertThat(result.get().getApplicationId()).isEqualTo("fdsa"); assertThat(result.get().getApplicationVersion()).isEqualTo("6478e18"); verify(ec2InstanceContextMock).isTaupageAmi(); verify(ec2InstanceContextMock).getInstanceId(); verify(ec2InstanceContextMock).getClient(eq(AmazonEC2Client.class)); verify(amazonEC2ClientMock).describeInstanceAttribute(any()); }
@Test public void testApplyWithTaupageAmiButInvalidYaml() throws Exception { // a yaml list is not a valid taupage format. Map is required. final String yamlData = "- a\n- b\n- c\n"; when(ec2InstanceContextMock.isTaupageAmi()).thenReturn(Optional.of(true)); when(ec2InstanceContextMock.getInstanceId()).thenReturn(INSTANCE_ID); when(ec2InstanceContextMock.getClient(eq(AmazonEC2Client.class))).thenReturn(amazonEC2ClientMock); when(amazonEC2ClientMock.describeInstanceAttribute(any())).thenReturn(new DescribeInstanceAttributeResult(). withInstanceAttribute(new InstanceAttribute() .withUserData(Base64.encodeAsString(yamlData.getBytes())))); final Optional<TaupageYaml> result = taupageYamlProvider.apply(ec2InstanceContextMock); assertThat(result).isEmpty(); verify(ec2InstanceContextMock).isTaupageAmi(); verify(ec2InstanceContextMock).getInstanceId(); verify(ec2InstanceContextMock).getClient(eq(AmazonEC2Client.class)); verify(amazonEC2ClientMock).describeInstanceAttribute(any()); }
private void fillMissingProperties(Instance instance) { try { InstanceAttribute instanceAttribute = describeInstanceAttribute( instance.getInstanceId(), InstanceAttributeName.SriovNetSupport); String sriovNetSupport = instanceAttribute.getSriovNetSupport(); instance.setSriovNetSupport(sriovNetSupport); } catch (AmazonServiceException e) { // In practice, users may not have appropriate IAM permission for // DescribeInstanceAttribute. We need to be more forgiving in those cases, // and simply leave a warning in the log here. LOG.warn("Could not fill missing properties. Failed to perform " + "DescribeInstanceAttribute action.", e); } }
/** * Retrieves an instance attribute. * * @param instanceId instance ID * @param attribute name of attribute to describe * @return attribute */ @VisibleForTesting InstanceAttribute describeInstanceAttribute(String instanceId, InstanceAttributeName attribute) { DescribeInstanceAttributeRequest request = new DescribeInstanceAttributeRequest() .withInstanceId(instanceId) .withAttribute(attribute); return client.describeInstanceAttribute(request).getInstanceAttribute(); }
@Override public DescribeInstanceAttributeResult describeInstanceAttribute(AmazonEC2Client ec2Client, DescribeInstanceAttributeRequest describeInstanceAttributeRequest) { InstanceAttribute instanceAttribute = new InstanceAttribute(); instanceAttribute.withGroups(new GroupIdentifier().withGroupId("A_TEST_SECURITY_GROUP")); return new DescribeInstanceAttributeResult().withInstanceAttribute(instanceAttribute); }
@Override public Optional<TaupageYaml> getTaupageYaml(final String instanceId, final String account, final String region) { final AmazonEC2Client client = clientProvider.getClient(AmazonEC2Client.class, account, Region.getRegion(Regions.fromName(region))); try { final DescribeInstanceAttributeResult response = client.describeInstanceAttribute( new DescribeInstanceAttributeRequest() .withInstanceId(instanceId) .withAttribute(USER_DATA)); return ofNullable(response) .map(DescribeInstanceAttributeResult::getInstanceAttribute) .map(InstanceAttribute::getUserData) .map(Base64::decode) .map(String::new) .map(TaupageYamlUtil::parseTaupageYaml); } catch (final AmazonClientException e) { log.warn("Could not get Taupage YAML for instance: " + instanceId, e); return empty(); } catch (YAMLException | IllegalArgumentException s) { log.warn("Taupage YAML is not valid for instance: " + instanceId, s); return empty(); } }
@Test public void testGetTaupageYaml() throws Exception { when(amazonEC2ClientMock.describeInstanceAttribute(any())).thenReturn(new DescribeInstanceAttributeResult(). withInstanceAttribute(new InstanceAttribute() .withUserData(Base64.encodeAsString("blub: fdsa".getBytes())))); final FetchTaupageYaml fetchTaupageYaml = new FetchTaupageYamlImpl(clientProviderMock); final Optional<TaupageYaml> result = fetchTaupageYaml.getTaupageYaml(INSTANCE_ID, ACCOUNT, REGION); assertThat(result).isPresent(); verify(amazonEC2ClientMock).describeInstanceAttribute(any()); }
private Optional<TaupageYaml> getTaupageYaml(@Nonnull final EC2InstanceContext context) { if (context.isTaupageAmi().orElse(false)) { final String instanceId = context.getInstanceId(); try { return Optional.of(context.getClient(AmazonEC2Client.class)) .map(client -> client.describeInstanceAttribute(new DescribeInstanceAttributeRequest() .withInstanceId(instanceId) .withAttribute(USER_DATA))) .map(DescribeInstanceAttributeResult::getInstanceAttribute) .map(InstanceAttribute::getUserData) .map(Base64::decode) .map(String::new) .map(TaupageYamlUtil::parseTaupageYaml); } catch (final AmazonClientException e) { log.warn("Could not get Taupage YAML for instance: " + instanceId, e); return empty(); } catch (YAMLException | IllegalArgumentException s) { log.warn("Taupage YAML is not valid for instance: " + instanceId, s); return empty(); } } else { return empty(); } }
private VirtualMachine toExcaliburInstance(Instance instance, KeyPair keyPair) { Map<String, Tag> tags = TAGS.apply(instance.getTags()); VirtualMachine vm = new VirtualMachine() .setName(instance.getInstanceId()) .setImageId(instance.getImageId()) .setType(InstanceType.valueOf(instance.getInstanceType()).setProvider(this.credentials_.getProvider())) .setState(new InstanceStateDetails(InstanceStateType.valueOfFrom(instance.getState().getName()), new Date())) //TODO we need to improve this .setConfiguration( new VmConfiguration() .setKeyName(instance.getKeyName()) .setKeyPairs(new KeyPairs().setPrivateKey(keyPair)) .setPlatform(isNullOrEmpty(instance.getPlatform()) ? DEFAULT_PLATFORM : instance.getPlatform()) .setPlatformUserName(tags.get(DEFAULT_PLATFORM_INSTANCE_USERNAME_TAG) != null ? tags.get(DEFAULT_PLATFORM_INSTANCE_USERNAME_TAG).getValue() : System.getProperty("org.excalibur.default.platform.username")) .setPrivateIpAddress(instance.getPrivateIpAddress()).setPublicIpAddress(instance.getPublicIpAddress()) .setPublicDnsName(instance.getPublicDnsName())).setLaunchTime(instance.getLaunchTime()) // .setLocation(new Region().setName(instance.getPlacement().getAvailabilityZone())) // .setLocation(credentials_.getRegion()) .setLocation(new Zone().setName(instance.getPlacement().getAvailabilityZone()).setRegion(credentials_.getRegion())) .setPlacement(new org.excalibur.core.cloud.api.Placement() .setGroupName(instance.getPlacement().getGroupName()) .setZone(instance.getPlacement().getAvailabilityZone())) .setOwner(new User(this.credentials_.getUserId()).setUsername(tags.get("username") != null ? tags.get("username").getValue(): null)); if (tags.containsKey("keyname")) { if (vm.getConfiguration().getKeyPairs().getPrivateKey() == null) { vm.getConfiguration().getKeyPairs().setPrivateKey(new KeyPair()); } vm.getConfiguration().getKeyPairs().getPrivateKey().setKeyName(tags.get("keyname").getValue()); } else { return null; } InstanceAttribute attribute = new AmazonEC2Client(awsCredentials_).describeInstanceAttribute( new DescribeInstanceAttributeRequest().withInstanceId(instance.getInstanceId()).withAttribute("userData")).getInstanceAttribute(); // List<InstanceStatus> instanceStatuses = new AmazonEC2Client(awsCredentials_).describeInstanceStatus( // new DescribeInstanceStatusRequest().withInstanceIds(instance.getInstanceId())).getInstanceStatuses(); if (!isNullOrEmpty(attribute.getUserData())) { String userData = new String(Base64.decodeBase64(attribute.getUserData().getBytes())); int i = userData.indexOf("#start-data"), f = userData.indexOf("#end-data"); if (i > -1 && f > -1) { String[] keys = userData.substring(i, f).split("#"); checkState(keys.length == 4); vm.getConfiguration().getKeyPairs().getPrivateKey().setKeyMaterial(keys[2]); vm.getConfiguration().getKeyPairs() .setPublicKey(new KeyPair().setKeyName(tags.get("keyname").getValue()).setKeyMaterial(keys[3].trim())); } vm.setUserData(attribute.getUserData()); } for (Tag tag: tags.values()) { vm.getTags().add(org.excalibur.core.cloud.api.domain.Tag.valueOf(tag.getKey(), tag.getValue())); } return vm; }
InstanceAttribute getInstanceAttribute(String instanceId, String attributeName) throws Exception;