Repository: apache/jclouds Branch: master Commit: 554418e58ac8 Files: 7733 Total size: 27.2 MB Directory structure: gitextract_4xvek8ry/ ├── .asf.yaml ├── .dir-locals.el ├── .gitattributes ├── .github/ │ └── workflows/ │ └── ci.yaml ├── .gitignore ├── .mailmap ├── CONTRIBUTING.md ├── README.md ├── all/ │ └── pom.xml ├── allblobstore/ │ └── pom.xml ├── allcompute/ │ └── pom.xml ├── allloadbalancer/ │ └── pom.xml ├── apis/ │ ├── atmos/ │ │ ├── README.txt │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── atmos/ │ │ │ ├── AtmosApiMetadata.java │ │ │ ├── AtmosClient.java │ │ │ ├── AtmosResponseException.java │ │ │ ├── binders/ │ │ │ │ ├── BindMetadataToHeaders.java │ │ │ │ └── BindUserMetadataToHeaders.java │ │ │ ├── blobstore/ │ │ │ │ ├── AtmosBlobRequestSigner.java │ │ │ │ ├── AtmosBlobStore.java │ │ │ │ ├── config/ │ │ │ │ │ └── AtmosBlobStoreContextModule.java │ │ │ │ └── functions/ │ │ │ │ ├── BlobMetadataToObject.java │ │ │ │ ├── BlobStoreListOptionsToListOptions.java │ │ │ │ ├── BlobToContentMetadata.java │ │ │ │ ├── BlobToObject.java │ │ │ │ ├── BlobToSystemMetadata.java │ │ │ │ ├── DirectoryEntryListToResourceMetadataList.java │ │ │ │ ├── ObjectToBlob.java │ │ │ │ └── ObjectToBlobMetadata.java │ │ │ ├── config/ │ │ │ │ ├── AtmosHttpApiModule.java │ │ │ │ ├── AtmosObjectModule.java │ │ │ │ └── AtmosParserModule.java │ │ │ ├── domain/ │ │ │ │ ├── AtmosError.java │ │ │ │ ├── AtmosObject.java │ │ │ │ ├── BoundedSet.java │ │ │ │ ├── DirectoryEntry.java │ │ │ │ ├── FileType.java │ │ │ │ ├── MutableContentMetadata.java │ │ │ │ ├── SystemMetadata.java │ │ │ │ ├── UploadInfo.java │ │ │ │ ├── UserMetadata.java │ │ │ │ └── internal/ │ │ │ │ ├── AtmosObjectImpl.java │ │ │ │ ├── BoundedLinkedHashSet.java │ │ │ │ └── DelegatingMutableContentMetadata.java │ │ │ ├── fallbacks/ │ │ │ │ ├── EndpointIfAlreadyExists.java │ │ │ │ └── TrueOn404FalseOnPathNotEmpty.java │ │ │ ├── filters/ │ │ │ │ ├── ShareUrl.java │ │ │ │ └── SignRequest.java │ │ │ ├── functions/ │ │ │ │ ├── AtmosObjectName.java │ │ │ │ ├── ParseDirectoryListFromContentAndHeaders.java │ │ │ │ ├── ParseObjectFromHeadersAndHttpContent.java │ │ │ │ ├── ParseSystemMetadataFromHeaders.java │ │ │ │ ├── ParseUserMetadataFromHeaders.java │ │ │ │ └── ReturnTrueIfGroupACLIsOtherRead.java │ │ │ ├── handlers/ │ │ │ │ ├── AtmosClientErrorRetryHandler.java │ │ │ │ ├── AtmosServerErrorRetryHandler.java │ │ │ │ └── ParseAtmosErrorFromXmlContent.java │ │ │ ├── options/ │ │ │ │ ├── ListOptions.java │ │ │ │ └── PutOptions.java │ │ │ ├── reference/ │ │ │ │ ├── AtmosErrorCode.java │ │ │ │ └── AtmosHeaders.java │ │ │ ├── util/ │ │ │ │ └── AtmosUtils.java │ │ │ └── xml/ │ │ │ ├── ErrorHandler.java │ │ │ └── ListDirectoryResponseHandler.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── atmos/ │ │ │ ├── AtmosApiMetadataTest.java │ │ │ ├── AtmosClientLiveTest.java │ │ │ ├── AtmosClientTest.java │ │ │ ├── binders/ │ │ │ │ ├── BindMetadataToHeadersTest.java │ │ │ │ └── BindUserMetadataToHeadersTest.java │ │ │ ├── blobstore/ │ │ │ │ ├── AtmosBlobRequestSignerTest.java │ │ │ │ ├── functions/ │ │ │ │ │ ├── ListOptionsToBlobStoreListOptions.java │ │ │ │ │ └── ResourceMetadataListToDirectoryEntryList.java │ │ │ │ └── integration/ │ │ │ │ ├── AtmosBlobSignerLiveTest.java │ │ │ │ ├── AtmosContainerIntegrationLiveTest.java │ │ │ │ ├── AtmosContainerLiveTest.java │ │ │ │ ├── AtmosIntegrationLiveTest.java │ │ │ │ ├── AtmosLiveTest.java │ │ │ │ └── AtmosServiceIntegrationLiveTest.java │ │ │ ├── fallbacks/ │ │ │ │ └── EndpointIfAlreadyExistsTest.java │ │ │ ├── filters/ │ │ │ │ └── SignRequestTest.java │ │ │ ├── functions/ │ │ │ │ ├── AtmosObjectNameTest.java │ │ │ │ ├── ParseDirectoryListFromContentAndHeadersTest.java │ │ │ │ ├── ParseObjectFromHeadersAndHttpContentTest.java │ │ │ │ ├── ParseSystemMetadataFromHeadersTest.java │ │ │ │ └── ParseUserMetadataFromHeadersTest.java │ │ │ ├── handlers/ │ │ │ │ └── AtmosServerErrorRetryHandlerTest.java │ │ │ ├── options/ │ │ │ │ └── ListOptionsTest.java │ │ │ └── xml/ │ │ │ ├── ErrorHandlerTest.java │ │ │ └── ListDirectoryResponseHandlerTest.java │ │ └── resources/ │ │ ├── error.xml │ │ ├── hashstring.txt │ │ ├── list_basic.xml │ │ ├── list_meta.xml │ │ └── log4j.xml │ ├── byon/ │ │ ├── README.txt │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── byon/ │ │ │ ├── BYONApiMetadata.java │ │ │ ├── Node.java │ │ │ ├── config/ │ │ │ │ ├── BYONComputeServiceContextModule.java │ │ │ │ ├── CacheNodeStoreModule.java │ │ │ │ ├── ConfiguresNodeStore.java │ │ │ │ └── YamlNodeStoreModule.java │ │ │ ├── domain/ │ │ │ │ └── YamlNode.java │ │ │ ├── functions/ │ │ │ │ ├── NodeToNodeMetadata.java │ │ │ │ └── NodesFromYamlStream.java │ │ │ ├── internal/ │ │ │ │ └── BYONComputeServiceAdapter.java │ │ │ └── suppliers/ │ │ │ ├── NodesParsedFromSupplier.java │ │ │ └── SupplyFromProviderURIOrNodesProperty.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── byon/ │ │ │ ├── BYONApiMetadataTest.java │ │ │ ├── BYONComputeServiceLiveTest.java │ │ │ ├── BYONComputeServiceTest.java │ │ │ ├── config/ │ │ │ │ ├── CacheNodeStoreModuleTest.java │ │ │ │ └── YamlNodeStoreModuleTest.java │ │ │ ├── functions/ │ │ │ │ ├── NodeToNodeMetadataTest.java │ │ │ │ └── NodesFromYamlTest.java │ │ │ └── suppliers/ │ │ │ ├── NodesParsedFromSupplierTest.java │ │ │ └── SupplyFromProviderURIOrNodesPropertyTest.java │ │ └── resources/ │ │ ├── log4j.xml │ │ ├── test1.yaml │ │ ├── test_location.yaml │ │ ├── test_with_url.yaml │ │ └── testkey.txt │ ├── chef/ │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ ├── chef/ │ │ │ │ ├── ChefApi.java │ │ │ │ ├── ChefApiMetadata.java │ │ │ │ ├── ChefService.java │ │ │ │ ├── binders/ │ │ │ │ │ ├── BindChecksumsToJsonPayload.java │ │ │ │ │ ├── BindCreateClientOptionsToJsonPayload.java │ │ │ │ │ ├── BindGenerateKeyForClientToJsonPayload.java │ │ │ │ │ ├── BindGroupToUpdateRequestJsonPayload.java │ │ │ │ │ ├── DatabagItemId.java │ │ │ │ │ ├── EnvironmentName.java │ │ │ │ │ ├── GroupName.java │ │ │ │ │ ├── NodeName.java │ │ │ │ │ └── RoleName.java │ │ │ │ ├── config/ │ │ │ │ │ ├── ChefBootstrapModule.java │ │ │ │ │ ├── ChefHttpApiModule.java │ │ │ │ │ ├── ChefParserModule.java │ │ │ │ │ ├── ChefProperties.java │ │ │ │ │ ├── InstallChef.java │ │ │ │ │ └── Validator.java │ │ │ │ ├── domain/ │ │ │ │ │ ├── Attribute.java │ │ │ │ │ ├── BootstrapConfig.java │ │ │ │ │ ├── ChecksumStatus.java │ │ │ │ │ ├── Client.java │ │ │ │ │ ├── CookbookDefinition.java │ │ │ │ │ ├── CookbookVersion.java │ │ │ │ │ ├── DatabagItem.java │ │ │ │ │ ├── Environment.java │ │ │ │ │ ├── Group.java │ │ │ │ │ ├── Grouping.java │ │ │ │ │ ├── Metadata.java │ │ │ │ │ ├── Node.java │ │ │ │ │ ├── Resource.java │ │ │ │ │ ├── Role.java │ │ │ │ │ ├── Sandbox.java │ │ │ │ │ ├── SearchResult.java │ │ │ │ │ ├── UploadSandbox.java │ │ │ │ │ └── User.java │ │ │ │ ├── features/ │ │ │ │ │ └── OrganizationApi.java │ │ │ │ ├── filters/ │ │ │ │ │ └── SignedHeaderAuth.java │ │ │ │ ├── functions/ │ │ │ │ │ ├── BootstrapConfigForGroup.java │ │ │ │ │ ├── ClientForGroup.java │ │ │ │ │ ├── GroupToBootScript.java │ │ │ │ │ ├── ParseCookbookDefinitionFromJson.java │ │ │ │ │ ├── ParseCookbookDefinitionListFromJson.java │ │ │ │ │ ├── ParseCookbookNamesFromJson.java │ │ │ │ │ ├── ParseCookbookVersionsFromJson.java │ │ │ │ │ ├── ParseErrorFromJsonOrReturnBody.java │ │ │ │ │ ├── ParseKeySetFromJson.java │ │ │ │ │ ├── ParseSearchClientsFromJson.java │ │ │ │ │ ├── ParseSearchDatabagFromJson.java │ │ │ │ │ ├── ParseSearchEnvironmentsFromJson.java │ │ │ │ │ ├── ParseSearchNodesFromJson.java │ │ │ │ │ ├── ParseSearchResultFromJson.java │ │ │ │ │ ├── ParseSearchRolesFromJson.java │ │ │ │ │ └── UriForResource.java │ │ │ │ ├── handlers/ │ │ │ │ │ ├── ChefApiErrorRetryHandler.java │ │ │ │ │ └── ChefErrorHandler.java │ │ │ │ ├── internal/ │ │ │ │ │ └── BaseChefService.java │ │ │ │ ├── options/ │ │ │ │ │ ├── CreateClientOptions.java │ │ │ │ │ └── SearchOptions.java │ │ │ │ ├── predicates/ │ │ │ │ │ └── CookbookVersionPredicates.java │ │ │ │ ├── strategy/ │ │ │ │ │ ├── CleanupStaleNodesAndClients.java │ │ │ │ │ ├── CreateNodeAndPopulateAutomaticAttributes.java │ │ │ │ │ ├── DeleteAllClientsInList.java │ │ │ │ │ ├── DeleteAllNodesInList.java │ │ │ │ │ ├── ListClients.java │ │ │ │ │ ├── ListCookbookVersions.java │ │ │ │ │ ├── ListCookbookVersionsInEnvironment.java │ │ │ │ │ ├── ListEnvironments.java │ │ │ │ │ ├── ListNodes.java │ │ │ │ │ ├── ListNodesInEnvironment.java │ │ │ │ │ ├── UpdateAutomaticAttributesOnNode.java │ │ │ │ │ └── internal/ │ │ │ │ │ ├── BaseListCookbookVersionsImpl.java │ │ │ │ │ ├── BaseListNodesImpl.java │ │ │ │ │ ├── CleanupStaleNodesAndClientsImpl.java │ │ │ │ │ ├── CreateNodeAndPopulateAutomaticAttributesImpl.java │ │ │ │ │ ├── DeleteAllClientsInListImpl.java │ │ │ │ │ ├── DeleteAllNodesInListImpl.java │ │ │ │ │ ├── ListClientsImpl.java │ │ │ │ │ ├── ListCookbookVersionsImpl.java │ │ │ │ │ ├── ListCookbookVersionsInEnvironmentImpl.java │ │ │ │ │ ├── ListEnvironmentsImpl.java │ │ │ │ │ ├── ListNodesImpl.java │ │ │ │ │ ├── ListNodesInEnvironmentImpl.java │ │ │ │ │ └── UpdateAutomaticAttributesOnNodeImpl.java │ │ │ │ ├── suppliers/ │ │ │ │ │ └── ChefVersionSupplier.java │ │ │ │ └── util/ │ │ │ │ ├── ChefUtils.java │ │ │ │ ├── CollectionUtils.java │ │ │ │ └── RunListBuilder.java │ │ │ └── ohai/ │ │ │ ├── Automatic.java │ │ │ ├── AutomaticSupplier.java │ │ │ ├── config/ │ │ │ │ ├── ConfiguresOhai.java │ │ │ │ ├── JMXOhaiModule.java │ │ │ │ └── OhaiModule.java │ │ │ ├── functions/ │ │ │ │ ├── ByteArrayToMacAddress.java │ │ │ │ ├── MapSetToMultimap.java │ │ │ │ └── NestSlashKeys.java │ │ │ └── suppliers/ │ │ │ └── UptimeSecondsSupplier.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ ├── chef/ │ │ │ │ ├── BaseChefApiExpectTest.java │ │ │ │ ├── ChefApiDelegationTest.java │ │ │ │ ├── ChefApiExpectTest.java │ │ │ │ ├── ChefApiLiveTest.java │ │ │ │ ├── ChefApiMetadataTest.java │ │ │ │ ├── ChefApiTest.java │ │ │ │ ├── binders/ │ │ │ │ │ ├── BindGroupToUpdateRequestJsonPayloadTest.java │ │ │ │ │ ├── BindHexEncodedMD5sToJsonPayloadTest.java │ │ │ │ │ └── GroupNameTest.java │ │ │ │ ├── config/ │ │ │ │ │ └── ChefParserModuleTest.java │ │ │ │ ├── domain/ │ │ │ │ │ └── RoleTest.java │ │ │ │ ├── features/ │ │ │ │ │ ├── OrganizationApiExpectTest.java │ │ │ │ │ └── OrganizationApiLiveTest.java │ │ │ │ ├── filters/ │ │ │ │ │ └── SignedHeaderAuthTest.java │ │ │ │ ├── functions/ │ │ │ │ │ ├── BootstrapConfigForGroupTest.java │ │ │ │ │ ├── ClientForGroupTest.java │ │ │ │ │ ├── GroupToBootScriptTest.java │ │ │ │ │ ├── ParseClientFromJsonTest.java │ │ │ │ │ ├── ParseCookbookDefinitionFromJsonTest.java │ │ │ │ │ ├── ParseCookbookDefinitionListFromJsonTest.java │ │ │ │ │ ├── ParseCookbookNamesFromJsonTest.java │ │ │ │ │ ├── ParseCookbookVersionFromJsonTest.java │ │ │ │ │ ├── ParseCookbookVersionsFromJsonTest.java │ │ │ │ │ ├── ParseDataBagItemFromJsonTest.java │ │ │ │ │ ├── ParseErrorFromJsonOrReturnBodyTest.java │ │ │ │ │ ├── ParseKeySetFromJsonTest.java │ │ │ │ │ ├── ParseNodeFromJsonTest.java │ │ │ │ │ ├── ParseSandboxFromJsonTest.java │ │ │ │ │ ├── ParseSearchDataBagItemFromJsonTest.java │ │ │ │ │ ├── ParseUploadSandboxFromJsonTest.java │ │ │ │ │ └── UriForResourceTest.java │ │ │ │ ├── handlers/ │ │ │ │ │ └── ChefApiErrorRetryHandlerTest.java │ │ │ │ ├── internal/ │ │ │ │ │ ├── BaseChefLiveTest.java │ │ │ │ │ └── BaseChefServiceTest.java │ │ │ │ ├── strategy/ │ │ │ │ │ └── internal/ │ │ │ │ │ ├── CleanupStaleNodesAndClientsImplLiveTest.java │ │ │ │ │ ├── CreateNodeAndPopulateAutomaticAttributesImplLiveTest.java │ │ │ │ │ ├── CreateNodeAndPopulateAutomaticAttributesImplTest.java │ │ │ │ │ ├── DeleteAllApisAndNodesInListImplLiveTest.java │ │ │ │ │ ├── ListCookbookVersionsInEnvironmentImplLiveTest.java │ │ │ │ │ ├── ListNodesImplLiveTest.java │ │ │ │ │ ├── ListNodesInEnvironmentImplLiveTest.java │ │ │ │ │ ├── UpdateAutomaticAttributesOnNodeImplLiveTest.java │ │ │ │ │ └── UpdateAutomaticAttributesOnNodeImplTest.java │ │ │ │ ├── suppliers/ │ │ │ │ │ └── ChefVersionSupplierTest.java │ │ │ │ └── util/ │ │ │ │ ├── ChefUtilsTest.java │ │ │ │ └── RunListBuilderTest.java │ │ │ └── ohai/ │ │ │ ├── config/ │ │ │ │ ├── JMXTest.java │ │ │ │ └── OhaiModuleTest.java │ │ │ └── functions/ │ │ │ ├── ByteArrayToMacAddressTest.java │ │ │ └── NestSlashKeysTest.java │ │ └── resources/ │ │ ├── apache-chef-demo-cookbook.json │ │ ├── bootstrap-env-noattrs.sh │ │ ├── bootstrap-env.sh │ │ ├── bootstrap-node-env.sh │ │ ├── bootstrap-ssl.sh │ │ ├── bootstrap.sh │ │ ├── brew-cookbook.json │ │ ├── chef.crt │ │ ├── client-no-pub-key.json │ │ ├── client.json │ │ ├── clients_list.json │ │ ├── data_list.json │ │ ├── env_cookbooks.json │ │ ├── environment_recipes.json │ │ ├── group-update.json │ │ ├── group.json │ │ ├── groups.json │ │ ├── logback.xml │ │ ├── mysql-cookbook.json │ │ ├── node.json │ │ ├── nodes_list.json │ │ ├── privkey.txt │ │ ├── pubkey.txt │ │ ├── roles_list.json │ │ ├── sandbox.json │ │ ├── search_role.json │ │ ├── search_role_empty.json │ │ ├── tomcat-cookbook.json │ │ ├── upload-site.json │ │ └── user.json │ ├── cloudstack/ │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── cloudstack/ │ │ │ ├── AsyncJobException.java │ │ │ ├── CloudStackApi.java │ │ │ ├── CloudStackApiMetadata.java │ │ │ ├── CloudStackContext.java │ │ │ ├── CloudStackDomainApi.java │ │ │ ├── CloudStackGlobalApi.java │ │ │ ├── binders/ │ │ │ │ ├── BindAccountSecurityGroupPairsToIndexedQueryParams.java │ │ │ │ ├── BindCIDRsToCommaDelimitedQueryParam.java │ │ │ │ ├── BindIdListToCommaDelimitedQueryParam.java │ │ │ │ ├── BindSnapshotPolicyScheduleToQueryParam.java │ │ │ │ ├── BindTemplateMetadataToQueryParams.java │ │ │ │ └── ResourceLimitToQueryParams.java │ │ │ ├── compute/ │ │ │ │ ├── CloudStackComputeService.java │ │ │ │ ├── config/ │ │ │ │ │ └── CloudStackComputeServiceContextModule.java │ │ │ │ ├── extensions/ │ │ │ │ │ ├── CloudStackImageExtension.java │ │ │ │ │ └── CloudStackSecurityGroupExtension.java │ │ │ │ ├── functions/ │ │ │ │ │ ├── CloudStackSecurityGroupToSecurityGroup.java │ │ │ │ │ ├── IngressRuleToIpPermission.java │ │ │ │ │ ├── OrphanedGroupsByZoneId.java │ │ │ │ │ ├── ServiceOfferingToHardware.java │ │ │ │ │ ├── TemplateToImage.java │ │ │ │ │ ├── TemplateToOperatingSystem.java │ │ │ │ │ ├── VirtualMachineToNodeMetadata.java │ │ │ │ │ └── ZoneToLocation.java │ │ │ │ ├── loaders/ │ │ │ │ │ ├── CreateUniqueKeyPair.java │ │ │ │ │ └── FindSecurityGroupOrCreate.java │ │ │ │ ├── options/ │ │ │ │ │ └── CloudStackTemplateOptions.java │ │ │ │ ├── predicates/ │ │ │ │ │ └── AllNodesInGroupTerminated.java │ │ │ │ └── strategy/ │ │ │ │ ├── AdvancedNetworkOptionsConverter.java │ │ │ │ ├── BasicNetworkOptionsConverter.java │ │ │ │ ├── CloudStackComputeServiceAdapter.java │ │ │ │ └── OptionsConverter.java │ │ │ ├── config/ │ │ │ │ ├── CloudStackHttpApiModule.java │ │ │ │ ├── CloudStackParserModule.java │ │ │ │ ├── CloudStackProperties.java │ │ │ │ └── CredentialType.java │ │ │ ├── domain/ │ │ │ │ ├── Account.java │ │ │ │ ├── Alert.java │ │ │ │ ├── AllocationState.java │ │ │ │ ├── ApiKeyPair.java │ │ │ │ ├── AsyncCreateResponse.java │ │ │ │ ├── AsyncJob.java │ │ │ │ ├── AsyncJobError.java │ │ │ │ ├── Capabilities.java │ │ │ │ ├── Capacity.java │ │ │ │ ├── Cluster.java │ │ │ │ ├── ConfigurationEntry.java │ │ │ │ ├── DiskOffering.java │ │ │ │ ├── Domain.java │ │ │ │ ├── EncryptedPasswordAndPrivateKey.java │ │ │ │ ├── Event.java │ │ │ │ ├── ExtractMode.java │ │ │ │ ├── FirewallRule.java │ │ │ │ ├── GuestIPType.java │ │ │ │ ├── Host.java │ │ │ │ ├── IPForwardingRule.java │ │ │ │ ├── ISO.java │ │ │ │ ├── ISOExtraction.java │ │ │ │ ├── ISOPermissions.java │ │ │ │ ├── IngressRule.java │ │ │ │ ├── JobResult.java │ │ │ │ ├── LoadBalancerRule.java │ │ │ │ ├── LoginResponse.java │ │ │ │ ├── NIC.java │ │ │ │ ├── Network.java │ │ │ │ ├── NetworkOffering.java │ │ │ │ ├── NetworkOfferingAvailabilityType.java │ │ │ │ ├── NetworkService.java │ │ │ │ ├── NetworkType.java │ │ │ │ ├── OSType.java │ │ │ │ ├── PermissionOperation.java │ │ │ │ ├── Pod.java │ │ │ │ ├── PortForwardingRule.java │ │ │ │ ├── Project.java │ │ │ │ ├── PublicIPAddress.java │ │ │ │ ├── ResourceLimit.java │ │ │ │ ├── SecurityGroup.java │ │ │ │ ├── ServiceOffering.java │ │ │ │ ├── Snapshot.java │ │ │ │ ├── SnapshotPolicy.java │ │ │ │ ├── SnapshotPolicySchedule.java │ │ │ │ ├── SshKeyPair.java │ │ │ │ ├── StoragePool.java │ │ │ │ ├── StorageType.java │ │ │ │ ├── SystemVmType.java │ │ │ │ ├── Tag.java │ │ │ │ ├── Template.java │ │ │ │ ├── TemplateExtraction.java │ │ │ │ ├── TemplateFilter.java │ │ │ │ ├── TemplateMetadata.java │ │ │ │ ├── TemplatePermission.java │ │ │ │ ├── TrafficType.java │ │ │ │ ├── UsageRecord.java │ │ │ │ ├── User.java │ │ │ │ ├── VMGroup.java │ │ │ │ ├── VirtualMachine.java │ │ │ │ ├── VlanIPRange.java │ │ │ │ ├── Volume.java │ │ │ │ ├── Zone.java │ │ │ │ ├── ZoneAndName.java │ │ │ │ └── ZoneSecurityGroupNamePortsCidrs.java │ │ │ ├── features/ │ │ │ │ ├── AccountApi.java │ │ │ │ ├── AddressApi.java │ │ │ │ ├── AsyncJobApi.java │ │ │ │ ├── ConfigurationApi.java │ │ │ │ ├── DomainAccountApi.java │ │ │ │ ├── DomainDomainApi.java │ │ │ │ ├── DomainLimitApi.java │ │ │ │ ├── DomainUserApi.java │ │ │ │ ├── EventApi.java │ │ │ │ ├── FirewallApi.java │ │ │ │ ├── GlobalAccountApi.java │ │ │ │ ├── GlobalAlertApi.java │ │ │ │ ├── GlobalCapacityApi.java │ │ │ │ ├── GlobalConfigurationApi.java │ │ │ │ ├── GlobalDomainApi.java │ │ │ │ ├── GlobalHostApi.java │ │ │ │ ├── GlobalOfferingApi.java │ │ │ │ ├── GlobalPodApi.java │ │ │ │ ├── GlobalStoragePoolApi.java │ │ │ │ ├── GlobalUsageApi.java │ │ │ │ ├── GlobalUserApi.java │ │ │ │ ├── GlobalVlanApi.java │ │ │ │ ├── GlobalZoneApi.java │ │ │ │ ├── GuestOSApi.java │ │ │ │ ├── HypervisorApi.java │ │ │ │ ├── ISOApi.java │ │ │ │ ├── LimitApi.java │ │ │ │ ├── LoadBalancerApi.java │ │ │ │ ├── NATApi.java │ │ │ │ ├── NetworkApi.java │ │ │ │ ├── OfferingApi.java │ │ │ │ ├── ProjectApi.java │ │ │ │ ├── SSHKeyPairApi.java │ │ │ │ ├── SecurityGroupApi.java │ │ │ │ ├── SessionApi.java │ │ │ │ ├── SnapshotApi.java │ │ │ │ ├── TagApi.java │ │ │ │ ├── TemplateApi.java │ │ │ │ ├── VMGroupApi.java │ │ │ │ ├── VirtualMachineApi.java │ │ │ │ ├── VolumeApi.java │ │ │ │ └── ZoneApi.java │ │ │ ├── filters/ │ │ │ │ ├── AddSessionKeyAndJSessionIdToRequest.java │ │ │ │ ├── AuthenticationFilter.java │ │ │ │ └── QuerySigner.java │ │ │ ├── functions/ │ │ │ │ ├── CloudStackFallbacks.java │ │ │ │ ├── CreateFirewallRulesForIP.java │ │ │ │ ├── CreatePortForwardingRulesForIP.java │ │ │ │ ├── CreateSecurityGroupIfNeeded.java │ │ │ │ ├── DateToYyyyMmDd.java │ │ │ │ ├── GetFirewallRulesByVirtualMachine.java │ │ │ │ ├── GetIPForwardingRulesByVirtualMachine.java │ │ │ │ ├── ParseAsyncJobFromHttpResponse.java │ │ │ │ ├── ParseAsyncJobsFromHttpResponse.java │ │ │ │ ├── ParseEventTypesFromHttpResponse.java │ │ │ │ ├── ParseIdToNameEntryFromHttpResponse.java │ │ │ │ ├── ParseIdToNameFromHttpResponse.java │ │ │ │ ├── ParseLoginResponseFromHttpResponse.java │ │ │ │ ├── ParseNamesFromHttpResponse.java │ │ │ │ ├── ParseTypedAsyncJob.java │ │ │ │ ├── ReuseOrAssociateNewPublicIPAddress.java │ │ │ │ ├── StaticNATVirtualMachineInNetwork.java │ │ │ │ ├── WindowsLoginCredentialsFromEncryptedData.java │ │ │ │ └── ZoneIdToZone.java │ │ │ ├── handlers/ │ │ │ │ ├── CloudStackErrorHandler.java │ │ │ │ └── InvalidateSessionAndRetryOn401AndLogoutOnClose.java │ │ │ ├── internal/ │ │ │ │ └── CloudStackContextImpl.java │ │ │ ├── loaders/ │ │ │ │ └── LoginWithPasswordCredentials.java │ │ │ ├── options/ │ │ │ │ ├── AccountInDomainOptions.java │ │ │ │ ├── AddClusterOptions.java │ │ │ │ ├── AddHostOptions.java │ │ │ │ ├── AddSecondaryStorageOptions.java │ │ │ │ ├── AssignVirtualMachineOptions.java │ │ │ │ ├── AssociateIPAddressOptions.java │ │ │ │ ├── CreateAccountOptions.java │ │ │ │ ├── CreateDiskOfferingOptions.java │ │ │ │ ├── CreateDomainOptions.java │ │ │ │ ├── CreateFirewallRuleOptions.java │ │ │ │ ├── CreateIPForwardingRuleOptions.java │ │ │ │ ├── CreateLoadBalancerRuleOptions.java │ │ │ │ ├── CreateNetworkOptions.java │ │ │ │ ├── CreatePodOptions.java │ │ │ │ ├── CreateServiceOfferingOptions.java │ │ │ │ ├── CreateSnapshotOptions.java │ │ │ │ ├── CreateTagsOptions.java │ │ │ │ ├── CreateTemplateOptions.java │ │ │ │ ├── CreateUserOptions.java │ │ │ │ ├── CreateVMGroupOptions.java │ │ │ │ ├── CreateVlanIPRangeOptions.java │ │ │ │ ├── CreateZoneOptions.java │ │ │ │ ├── DeleteHostOptions.java │ │ │ │ ├── DeleteISOOptions.java │ │ │ │ ├── DeleteTagsOptions.java │ │ │ │ ├── DeleteTemplateOptions.java │ │ │ │ ├── DeployVirtualMachineOptions.java │ │ │ │ ├── ExtractISOOptions.java │ │ │ │ ├── ExtractTemplateOptions.java │ │ │ │ ├── GenerateUsageRecordsOptions.java │ │ │ │ ├── ListAccountsOptions.java │ │ │ │ ├── ListAlertsOptions.java │ │ │ │ ├── ListAsyncJobsOptions.java │ │ │ │ ├── ListCapacityOptions.java │ │ │ │ ├── ListClustersOptions.java │ │ │ │ ├── ListConfigurationEntriesOptions.java │ │ │ │ ├── ListDiskOfferingsOptions.java │ │ │ │ ├── ListDomainChildrenOptions.java │ │ │ │ ├── ListDomainsOptions.java │ │ │ │ ├── ListEgressFirewallRulesOptions.java │ │ │ │ ├── ListEventsOptions.java │ │ │ │ ├── ListFirewallRulesOptions.java │ │ │ │ ├── ListHostsOptions.java │ │ │ │ ├── ListIPForwardingRulesOptions.java │ │ │ │ ├── ListISOsOptions.java │ │ │ │ ├── ListLoadBalancerRulesOptions.java │ │ │ │ ├── ListNetworkOfferingsOptions.java │ │ │ │ ├── ListNetworksOptions.java │ │ │ │ ├── ListOSTypesOptions.java │ │ │ │ ├── ListPodsOptions.java │ │ │ │ ├── ListPortForwardingRulesOptions.java │ │ │ │ ├── ListProjectsOptions.java │ │ │ │ ├── ListPublicIPAddressesOptions.java │ │ │ │ ├── ListResourceLimitsOptions.java │ │ │ │ ├── ListSSHKeyPairsOptions.java │ │ │ │ ├── ListSecurityGroupsOptions.java │ │ │ │ ├── ListServiceOfferingsOptions.java │ │ │ │ ├── ListSnapshotPoliciesOptions.java │ │ │ │ ├── ListSnapshotsOptions.java │ │ │ │ ├── ListStoragePoolsOptions.java │ │ │ │ ├── ListTagsOptions.java │ │ │ │ ├── ListTemplatesOptions.java │ │ │ │ ├── ListUsageRecordsOptions.java │ │ │ │ ├── ListUsersOptions.java │ │ │ │ ├── ListVMGroupsOptions.java │ │ │ │ ├── ListVirtualMachinesOptions.java │ │ │ │ ├── ListVlanIPRangesOptions.java │ │ │ │ ├── ListVolumesOptions.java │ │ │ │ ├── ListZonesOptions.java │ │ │ │ ├── RegisterISOOptions.java │ │ │ │ ├── RegisterTemplateOptions.java │ │ │ │ ├── StopVirtualMachineOptions.java │ │ │ │ ├── UpdateAccountOptions.java │ │ │ │ ├── UpdateClusterOptions.java │ │ │ │ ├── UpdateDiskOfferingOptions.java │ │ │ │ ├── UpdateDomainOptions.java │ │ │ │ ├── UpdateHostOptions.java │ │ │ │ ├── UpdateISOOptions.java │ │ │ │ ├── UpdateISOPermissionsOptions.java │ │ │ │ ├── UpdateLoadBalancerRuleOptions.java │ │ │ │ ├── UpdateNetworkOfferingOptions.java │ │ │ │ ├── UpdatePodOptions.java │ │ │ │ ├── UpdateServiceOfferingOptions.java │ │ │ │ ├── UpdateTemplateOptions.java │ │ │ │ ├── UpdateTemplatePermissionsOptions.java │ │ │ │ ├── UpdateUserOptions.java │ │ │ │ ├── UpdateVMGroupOptions.java │ │ │ │ ├── UpdateVirtualMachineOptions.java │ │ │ │ └── UpdateZoneOptions.java │ │ │ ├── predicates/ │ │ │ │ ├── CorrectHypervisorForZone.java │ │ │ │ ├── JobComplete.java │ │ │ │ ├── LoadBalancerRuleActive.java │ │ │ │ ├── NetworkOfferingPredicates.java │ │ │ │ ├── NetworkPredicates.java │ │ │ │ ├── OSCategoryIn.java │ │ │ │ ├── PublicIPAddressPredicates.java │ │ │ │ ├── SecurityGroupPredicates.java │ │ │ │ ├── SshKeyPairPredicates.java │ │ │ │ ├── TemplatePredicates.java │ │ │ │ ├── UserPredicates.java │ │ │ │ ├── VirtualMachineDestroyed.java │ │ │ │ ├── VirtualMachineExpunged.java │ │ │ │ ├── VirtualMachineRunning.java │ │ │ │ └── ZonePredicates.java │ │ │ ├── strategy/ │ │ │ │ └── BlockUntilJobCompletesAndReturnResult.java │ │ │ ├── suppliers/ │ │ │ │ ├── GetCurrentUser.java │ │ │ │ ├── NetworksForCurrentUser.java │ │ │ │ ├── ProjectsForCurrentUser.java │ │ │ │ └── ZoneIdToZoneSupplier.java │ │ │ └── util/ │ │ │ ├── ApiKeyPairs.java │ │ │ └── SnapshotPolicySchedules.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── cloudstack/ │ │ │ ├── CloudStackApiMetadataTest.java │ │ │ ├── CloudStackContextBuilderTest.java │ │ │ ├── PasswordAuthenticationExpectTest.java │ │ │ ├── compute/ │ │ │ │ ├── CloudStackComputeServiceAdapterExpectTest.java │ │ │ │ ├── CloudStackComputeServiceAdapterLiveTest.java │ │ │ │ ├── CloudStackComputeServiceLiveTest.java │ │ │ │ ├── CloudStackExperimentLiveTest.java │ │ │ │ ├── extensions/ │ │ │ │ │ ├── CloudStackImageExtensionExpectTest.java │ │ │ │ │ ├── CloudStackImageExtensionLiveTest.java │ │ │ │ │ ├── CloudStackSecurityGroupExtensionExpectTest.java │ │ │ │ │ └── CloudStackSecurityGroupExtensionLiveTest.java │ │ │ │ ├── functions/ │ │ │ │ │ ├── CloudStackSecurityGroupToSecurityGroupTest.java │ │ │ │ │ ├── IngressRuleToIpPermissionTest.java │ │ │ │ │ ├── ServiceOfferingToHardwareTest.java │ │ │ │ │ ├── TemplateToImageTest.java │ │ │ │ │ ├── TemplateToOperatingSystemTest.java │ │ │ │ │ ├── VirtualMachineToNodeMetadataTest.java │ │ │ │ │ └── ZoneToLocationTest.java │ │ │ │ ├── loaders/ │ │ │ │ │ ├── CreateUniqueKeyPairTest.java │ │ │ │ │ └── FindSecurityGroupOrCreateTest.java │ │ │ │ ├── options/ │ │ │ │ │ └── CloudStackTemplateOptionsTest.java │ │ │ │ └── strategy/ │ │ │ │ └── OptionsConverterTest.java │ │ │ ├── domain/ │ │ │ │ └── VirtualMachineTest.java │ │ │ ├── features/ │ │ │ │ ├── AccountApiExpectTest.java │ │ │ │ ├── AccountApiLiveTest.java │ │ │ │ ├── AccountApiTest.java │ │ │ │ ├── AddressApiLiveTest.java │ │ │ │ ├── AddressApiTest.java │ │ │ │ ├── AsyncJobApiLiveTest.java │ │ │ │ ├── AsyncJobApiTest.java │ │ │ │ ├── ConfigurationApiLiveTest.java │ │ │ │ ├── ConfigurationApiTest.java │ │ │ │ ├── DomainAccountApiLiveTest.java │ │ │ │ ├── DomainAccountApiTest.java │ │ │ │ ├── DomainDomainApiExpectTest.java │ │ │ │ ├── DomainDomainApiLiveTest.java │ │ │ │ ├── DomainLimitApiLiveTest.java │ │ │ │ ├── DomainLimitApiTest.java │ │ │ │ ├── DomainUserApiLiveTest.java │ │ │ │ ├── EventApiLiveTest.java │ │ │ │ ├── EventApiTest.java │ │ │ │ ├── FirewallApiExpectTest.java │ │ │ │ ├── FirewallApiLiveTest.java │ │ │ │ ├── FirewallApiTest.java │ │ │ │ ├── GlobalAccountApiLiveTest.java │ │ │ │ ├── GlobalAccountApiTest.java │ │ │ │ ├── GlobalAlertApiLiveTest.java │ │ │ │ ├── GlobalAlertApiTest.java │ │ │ │ ├── GlobalCapacityApiLiveTest.java │ │ │ │ ├── GlobalCapacityApiTest.java │ │ │ │ ├── GlobalConfigurationApiExpectTest.java │ │ │ │ ├── GlobalConfigurationApiLiveTest.java │ │ │ │ ├── GlobalDomainApiExpectTest.java │ │ │ │ ├── GlobalDomainApiLiveTest.java │ │ │ │ ├── GlobalHostApiExpectTest.java │ │ │ │ ├── GlobalHostApiLiveTest.java │ │ │ │ ├── GlobalHostApiTest.java │ │ │ │ ├── GlobalOfferingApiLiveTest.java │ │ │ │ ├── GlobalOfferingApiTest.java │ │ │ │ ├── GlobalPodApiExpectTest.java │ │ │ │ ├── GlobalPodApiLiveTest.java │ │ │ │ ├── GlobalStoragePoolApiLiveTest.java │ │ │ │ ├── GlobalStoragePoolApiTest.java │ │ │ │ ├── GlobalUsageApiLiveTest.java │ │ │ │ ├── GlobalUsageApiTest.java │ │ │ │ ├── GlobalUserApiLiveTest.java │ │ │ │ ├── GlobalUserApiTest.java │ │ │ │ ├── GlobalVlanApiExpectTest.java │ │ │ │ ├── GlobalVlanApiLiveTest.java │ │ │ │ ├── GlobalZoneApiExpectTest.java │ │ │ │ ├── GlobalZoneApiLiveTest.java │ │ │ │ ├── GuestOSApiLiveTest.java │ │ │ │ ├── GuestOSApiTest.java │ │ │ │ ├── HypervisorApiLiveTest.java │ │ │ │ ├── HypervisorApiTest.java │ │ │ │ ├── ISOApiExpectTest.java │ │ │ │ ├── ISOApiLiveTest.java │ │ │ │ ├── ISOApiTest.java │ │ │ │ ├── LimitApiLiveTest.java │ │ │ │ ├── LimitApiTest.java │ │ │ │ ├── LoadBalancerApiLiveTest.java │ │ │ │ ├── LoadBalancerApiTest.java │ │ │ │ ├── NATApiLiveTest.java │ │ │ │ ├── NATApiTest.java │ │ │ │ ├── NetworkApiLiveTest.java │ │ │ │ ├── NetworkApiTest.java │ │ │ │ ├── OfferingApiLiveTest.java │ │ │ │ ├── OfferingApiTest.java │ │ │ │ ├── ProjectApiExpectTest.java │ │ │ │ ├── ProjectApiLiveTest.java │ │ │ │ ├── ProjectApiTest.java │ │ │ │ ├── SSHKeyPairApiExpectTest.java │ │ │ │ ├── SSHKeyPairApiLiveTest.java │ │ │ │ ├── SSHKeyPairApiTest.java │ │ │ │ ├── SecurityGroupApiLiveTest.java │ │ │ │ ├── SecurityGroupApiTest.java │ │ │ │ ├── SessionApiExpectTest.java │ │ │ │ ├── SessionApiLiveTest.java │ │ │ │ ├── SnapshotApiLiveTest.java │ │ │ │ ├── SnapshotApiTest.java │ │ │ │ ├── TagApiExpectTest.java │ │ │ │ ├── TagApiLiveTest.java │ │ │ │ ├── TagApiTest.java │ │ │ │ ├── TemplateApiLiveTest.java │ │ │ │ ├── TemplateApiTest.java │ │ │ │ ├── VMGroupApiLiveTest.java │ │ │ │ ├── VMGroupApiTest.java │ │ │ │ ├── VirtualMachineApiExpectTest.java │ │ │ │ ├── VirtualMachineApiLiveTest.java │ │ │ │ ├── VirtualMachineApiTest.java │ │ │ │ ├── VolumeApiExpectTest.java │ │ │ │ ├── VolumeApiLiveTest.java │ │ │ │ ├── VolumeApiTest.java │ │ │ │ ├── ZoneApiExpectTest.java │ │ │ │ ├── ZoneApiLiveTest.java │ │ │ │ └── ZoneApiTest.java │ │ │ ├── filters/ │ │ │ │ └── QuerySignerTest.java │ │ │ ├── functions/ │ │ │ │ ├── BlockUntilJobCompletesAndReturnResultTest.java │ │ │ │ ├── CreateSecurityGroupIfNeededTest.java │ │ │ │ ├── ParseAsyncJobFromHttpResponseTest.java │ │ │ │ ├── ParseAsyncJobsFromHttpResponseTest.java │ │ │ │ ├── ReuseOrAssociateNewPublicIPAddressTest.java │ │ │ │ ├── StaticNATVirtualMachineInNetworkLiveTest.java │ │ │ │ └── WindowsLoginCredentialsFromEncryptedDataTest.java │ │ │ ├── handlers/ │ │ │ │ ├── CloudStackErrorHandlerTest.java │ │ │ │ └── InvalidateSessionAndRetryOn401AndLogoutOnCloseTest.java │ │ │ ├── internal/ │ │ │ │ ├── BaseCloudStackApiLiveTest.java │ │ │ │ ├── BaseCloudStackApiTest.java │ │ │ │ ├── BaseCloudStackComputeServiceContextExpectTest.java │ │ │ │ └── BaseCloudStackExpectTest.java │ │ │ ├── loaders/ │ │ │ │ └── LoginWithPasswordCredentialsTest.java │ │ │ ├── options/ │ │ │ │ ├── AddClusterOptionsTest.java │ │ │ │ ├── AddHostOptionsTest.java │ │ │ │ ├── AddSecondaryStorageOptionsTest.java │ │ │ │ ├── AssociateIPAddressOptionsTest.java │ │ │ │ ├── CreateAccountOptionsTest.java │ │ │ │ ├── CreateDiskOfferingOptionsTest.java │ │ │ │ ├── CreateIPForwardingRuleOptionsTest.java │ │ │ │ ├── CreateNetworkOptionsTest.java │ │ │ │ ├── CreatePodOptionsTest.java │ │ │ │ ├── CreateServiceOfferingOptionsTest.java │ │ │ │ ├── CreateTagsOptionsTest.java │ │ │ │ ├── CreateUserOptionsTest.java │ │ │ │ ├── CreateVlanIPRangeOptionsTest.java │ │ │ │ ├── DeleteHostOptionsTest.java │ │ │ │ ├── DeleteTagsOptionsTest.java │ │ │ │ ├── GenerateUsageRecordsOptionsTest.java │ │ │ │ ├── ListAccountsOptionsTest.java │ │ │ │ ├── ListAlertsOptionsTest.java │ │ │ │ ├── ListAsyncJobsOptionsTest.java │ │ │ │ ├── ListCapacityOptionsTest.java │ │ │ │ ├── ListClustersOptionsTest.java │ │ │ │ ├── ListDiskOfferingsOptionsTest.java │ │ │ │ ├── ListHostsOptionsTest.java │ │ │ │ ├── ListIPForwardingRulesOptionsTest.java │ │ │ │ ├── ListISOsOptionsTest.java │ │ │ │ ├── ListLoadBalancerRulesOptionsTest.java │ │ │ │ ├── ListNetworkOfferingsOptionsTest.java │ │ │ │ ├── ListNetworksOptionsTest.java │ │ │ │ ├── ListOSTypesOptionsTest.java │ │ │ │ ├── ListPodsOptionsTest.java │ │ │ │ ├── ListPortForwardingRulesOptionsTest.java │ │ │ │ ├── ListProjectsOptionsTest.java │ │ │ │ ├── ListPublicIPAddressesOptionsTest.java │ │ │ │ ├── ListSecurityGroupsOptionsTest.java │ │ │ │ ├── ListServiceOfferingsOptionsTest.java │ │ │ │ ├── ListStoragePoolsOptionsTest.java │ │ │ │ ├── ListTagsOptionsTest.java │ │ │ │ ├── ListTemplatesOptionsTest.java │ │ │ │ ├── ListUsageRecordsOptionsTest.java │ │ │ │ ├── ListUsersOptionsTest.java │ │ │ │ ├── ListVirtualMachinesOptionsTest.java │ │ │ │ ├── ListVlanIPRangesOptionsTest.java │ │ │ │ ├── ListZonesOptionsTest.java │ │ │ │ ├── UpdateAccountOptionsTest.java │ │ │ │ ├── UpdateClusterOptionsTest.java │ │ │ │ ├── UpdateDiskOfferingOptionsTest.java │ │ │ │ ├── UpdateHostOptionsTest.java │ │ │ │ ├── UpdateNetworkOfferingOptionsTest.java │ │ │ │ ├── UpdatePodOptionsTest.java │ │ │ │ ├── UpdateServiceOfferingOptionsTest.java │ │ │ │ └── UpdateUserOptionsTest.java │ │ │ ├── parse/ │ │ │ │ ├── DeleteIPForwardingRuleResponseTest.java │ │ │ │ ├── DeleteNetworkResponseTest.java │ │ │ │ ├── DeployVirtualMachineResponse3xTest.java │ │ │ │ ├── DeployVirtualMachineResponse4xTest.java │ │ │ │ ├── DisableStaticNATResponseTest.java │ │ │ │ ├── EnableStaticNATResponseWhereResponseDoesntHaveJobTest.java │ │ │ │ ├── JobResultResponseTest.java │ │ │ │ ├── ListAccountsResponseTest.java │ │ │ │ ├── ListAlertsResponseTest.java │ │ │ │ ├── ListCapabilitiesResponseTest.java │ │ │ │ ├── ListCapacityResponseTest.java │ │ │ │ ├── ListClustersResponseTest.java │ │ │ │ ├── ListConfigurationEntriesResponseTest.java │ │ │ │ ├── ListDiskOfferingsResponseTest.java │ │ │ │ ├── ListDomainsResponseTest.java │ │ │ │ ├── ListFirewallRulesResponseTest.java │ │ │ │ ├── ListHostsResponseTest.java │ │ │ │ ├── ListHypervisorsResponseTest.java │ │ │ │ ├── ListIPForwardingRulesResponseTest.java │ │ │ │ ├── ListLoadBalancerRulesResponseTest.java │ │ │ │ ├── ListNetworkOfferingsResponseTest.java │ │ │ │ ├── ListNetworksResponseTest.java │ │ │ │ ├── ListOSCategoriesResponseTest.java │ │ │ │ ├── ListOSTypesResponseTest.java │ │ │ │ ├── ListPodsResponseTest.java │ │ │ │ ├── ListPortForwardingRulesResponseTest.java │ │ │ │ ├── ListPublicIPAddressesResponseTest.java │ │ │ │ ├── ListSSHKeyPairsResponseTest.java │ │ │ │ ├── ListSecurityGroupsResponseTest.java │ │ │ │ ├── ListServiceOfferingsResponseTest.java │ │ │ │ ├── ListStoragePoolsResponseTest.java │ │ │ │ ├── ListTagsResponseTest.java │ │ │ │ ├── ListTemplatesResponseTest.java │ │ │ │ ├── ListUsageRecordsResponseTest.java │ │ │ │ ├── ListVirtualMachinesResponse3xTest.java │ │ │ │ ├── ListVirtualMachinesResponseTest.java │ │ │ │ ├── ListVlanIPRangesResponseTest.java │ │ │ │ ├── ListZonesResponseTest.java │ │ │ │ └── RegisterUserKeysResponseTest.java │ │ │ └── predicates/ │ │ │ ├── JobCompleteTest.java │ │ │ ├── NetworkPredicatesTest.java │ │ │ ├── OSCategoryInTest.java │ │ │ ├── PublicIPAddressPredicatesTest.java │ │ │ ├── SecurityGroupPredicatesTest.java │ │ │ ├── TemplatePredicatesTest.java │ │ │ ├── UserPredicatesTest.java │ │ │ ├── VirtualMachineDestroyedTest.java │ │ │ ├── VirtualMachineExpungedTest.java │ │ │ ├── VirtualMachineRunningTest.java │ │ │ └── ZonePredicatesTest.java │ │ └── resources/ │ │ ├── addclusterresponse.json │ │ ├── addhostresponse.json │ │ ├── addsecondarystorageresponse.json │ │ ├── authorizesecuritygroupingressresponse.json │ │ ├── cancelhostmaintenanceresponse.json │ │ ├── createdomainresponse.json │ │ ├── createegressfirewallrulesresponse.json │ │ ├── createfirewallrulesresponse.json │ │ ├── createkeypairresponse.json │ │ ├── createpodresponse.json │ │ ├── createportforwardingrulesresponse.json │ │ ├── createsecuritygroupresponse.json │ │ ├── createsshkeypairresponse-2.json │ │ ├── createsshkeypairresponse.json │ │ ├── createtagsresponse.json │ │ ├── createtemplateresponse-imageextension.json │ │ ├── createtemplateresponse.json │ │ ├── createvlaniprangeresponse.json │ │ ├── createzoneresponse.json │ │ ├── deletedomainresponse.json │ │ ├── deleteegressfirewallrulesresponse.json │ │ ├── deletefirewallrulesresponse.json │ │ ├── deleteipforwardingruleresponse.json │ │ ├── deletenetworkresponse.json │ │ ├── deleteportforwardingrulesresponse.json │ │ ├── deletesecuritygroupresponse.json │ │ ├── deletetagsresponse.json │ │ ├── deletetemplateresponse.json │ │ ├── deletezoneresponse.json │ │ ├── deployvirtualmachineresponse.json │ │ ├── deployvirtualmachineresponse4x.json │ │ ├── disablestaticnatresponse.json │ │ ├── enablestaticnatresponse-withoutjob.json │ │ ├── getdomainresponse.json │ │ ├── getegressfirewallrulesresponse.json │ │ ├── getfirewallrulesresponse.json │ │ ├── getisoresponse.json │ │ ├── getportforwardingrulesresponse.json │ │ ├── getsecuritygroupresponse.json │ │ ├── getsecuritygroupresponse_extension_byid.json │ │ ├── getsecuritygroupresponse_extension_byid_empty.json │ │ ├── getsecuritygroupresponse_extension_byid_with_cidr.json │ │ ├── getsecuritygroupresponse_extension_byid_with_group.json │ │ ├── getvmpasswordresponse.json │ │ ├── getzoneresponse-2.json │ │ ├── getzoneresponse.json │ │ ├── listaccountsresponse.json │ │ ├── listalertsresponse.json │ │ ├── listasyncjobsresponse.json │ │ ├── listcapabilitiesresponse.json │ │ ├── listcapacityresponse.json │ │ ├── listclustersresponse.json │ │ ├── listconfigurationsresponse.json │ │ ├── listdiskofferingsresponse.json │ │ ├── listdomainchildrenresponse.json │ │ ├── listdomainsresponse.json │ │ ├── listegressfirewallrulesresponse.json │ │ ├── listeventtypesresponse.json │ │ ├── listfirewallrulesresponse.json │ │ ├── listhostsresponse.json │ │ ├── listhypervisorsresponse.json │ │ ├── listipforwardingrulesresponse.json │ │ ├── listisosresponse.json │ │ ├── listloadbalancerrulesresponse.json │ │ ├── listnetworkofferingsresponse.json │ │ ├── listnetworksresponse-2.json │ │ ├── listnetworksresponse.json │ │ ├── listoscategoriesresponse.json │ │ ├── listostypesresponse.json │ │ ├── listpodsresponse.json │ │ ├── listportforwardingrulesresponse.json │ │ ├── listprojectsresponse.json │ │ ├── listpublicipaddressesresponse.json │ │ ├── listresourcelimitsresponse.json │ │ ├── listsecuritygroupsresponse.json │ │ ├── listserviceofferingsresponse.json │ │ ├── listsshkeypairsresponse.json │ │ ├── liststoragepoolsresponse.json │ │ ├── listtagsresponse.json │ │ ├── listtemplatesresponse-imageextension.json │ │ ├── listtemplatesresponse.json │ │ ├── listusagerecordsresponse.json │ │ ├── listvirtualmachinesresponse-imageextension.json │ │ ├── listvirtualmachinesresponse.json │ │ ├── listvirtualmachinesresponse3x.json │ │ ├── listvlaniprangesresponse.json │ │ ├── listvolumesresponse-imageextension.json │ │ ├── listzonesresponse.json │ │ ├── listzonesresponse_single.json │ │ ├── loginresponse.json │ │ ├── logoutresponse.json │ │ ├── preparehostformaintenanceresponse.json │ │ ├── queryasyncjobresultresponse-authorizeingress.json │ │ ├── queryasyncjobresultresponse-createtemplate-imageextension.json │ │ ├── queryasyncjobresultresponse-createtemplate.json │ │ ├── queryasyncjobresultresponse-createvolume.json │ │ ├── queryasyncjobresultresponse-extracttemplate.json │ │ ├── queryasyncjobresultresponse-ipaddress.json │ │ ├── queryasyncjobresultresponse-ipforwardingrule.json │ │ ├── queryasyncjobresultresponse-stopvirtualmachine-imageextension.json │ │ ├── queryasyncjobresultresponse-virtualmachine-securitygroup.json │ │ ├── queryasyncjobresultresponse-virtualmachine.json │ │ ├── reconnecthostresponse.json │ │ ├── registerisoresponse.json │ │ ├── registersshkeypairresponse.json │ │ ├── registeruserkeysresponse.json │ │ ├── revokesecuritygroupingressresponse.json │ │ ├── stopvirtualmachineresponse-imageextension.json │ │ ├── updateclusterresponse.json │ │ ├── updateconfigurationsresponse.json │ │ ├── updatedomainresponse.json │ │ ├── updatehostresponse.json │ │ ├── updatepodresponse.json │ │ └── updatezoneresponse.json │ ├── cloudwatch/ │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── cloudwatch/ │ │ │ ├── CloudWatch.java │ │ │ ├── CloudWatchApi.java │ │ │ ├── CloudWatchApiMetadata.java │ │ │ ├── binders/ │ │ │ │ ├── AlarmNamesBinder.java │ │ │ │ ├── GetMetricStatisticsBinder.java │ │ │ │ └── MetricDataBinder.java │ │ │ ├── config/ │ │ │ │ └── CloudWatchHttpApiModule.java │ │ │ ├── domain/ │ │ │ │ ├── Alarm.java │ │ │ │ ├── AlarmHistoryItem.java │ │ │ │ ├── AutoScalingConstants.java │ │ │ │ ├── ComparisonOperator.java │ │ │ │ ├── Datapoint.java │ │ │ │ ├── Dimension.java │ │ │ │ ├── DynamoDBConstants.java │ │ │ │ ├── EBSConstants.java │ │ │ │ ├── EC2Constants.java │ │ │ │ ├── ELBConstants.java │ │ │ │ ├── EMRConstants.java │ │ │ │ ├── GetMetricStatistics.java │ │ │ │ ├── GetMetricStatisticsResponse.java │ │ │ │ ├── HistoryItemType.java │ │ │ │ ├── ListMetricsResponse.java │ │ │ │ ├── Metric.java │ │ │ │ ├── MetricDatum.java │ │ │ │ ├── Namespaces.java │ │ │ │ ├── RDSConstants.java │ │ │ │ ├── SNSConstants.java │ │ │ │ ├── SQSConstants.java │ │ │ │ ├── StatisticValues.java │ │ │ │ ├── Statistics.java │ │ │ │ ├── StorageGatewayConstants.java │ │ │ │ └── Unit.java │ │ │ ├── features/ │ │ │ │ ├── AlarmApi.java │ │ │ │ └── MetricApi.java │ │ │ ├── functions/ │ │ │ │ ├── ISO8601Format.java │ │ │ │ ├── ListAlarmHistoryToPagedIterable.java │ │ │ │ ├── ListAlarmsToPagedIterable.java │ │ │ │ └── MetricsToPagedIterable.java │ │ │ ├── handlers/ │ │ │ │ └── CloudWatchErrorHandler.java │ │ │ ├── options/ │ │ │ │ ├── GetMetricStatisticsOptions.java │ │ │ │ ├── ListAlarmHistoryOptions.java │ │ │ │ ├── ListAlarmsForMetric.java │ │ │ │ ├── ListAlarmsOptions.java │ │ │ │ ├── ListMetricsOptions.java │ │ │ │ └── SaveAlarmOptions.java │ │ │ └── xml/ │ │ │ ├── AlarmHistoryItemHandler.java │ │ │ ├── DatapointHandler.java │ │ │ ├── DimensionHandler.java │ │ │ ├── GetMetricStatisticsResponseHandler.java │ │ │ ├── GetMetricStatisticsResponseHandlerV2.java │ │ │ ├── ListAlarmHistoryResponseHandler.java │ │ │ ├── ListAlarmsForMetricResponseHandler.java │ │ │ ├── ListAlarmsResponseHandler.java │ │ │ ├── ListMetricsResponseHandler.java │ │ │ ├── MetricAlarmHandler.java │ │ │ └── MetricHandler.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── cloudwatch/ │ │ │ ├── CloudWatchApiMetadataTest.java │ │ │ ├── CloudWatchLiveTest.java │ │ │ ├── CloudWatchTest.java │ │ │ ├── binders/ │ │ │ │ ├── AlarmNamesBinderTest.java │ │ │ │ └── MetricDataBinderTest.java │ │ │ ├── features/ │ │ │ │ ├── AlarmApiExpectTest.java │ │ │ │ ├── AlarmApiLiveTest.java │ │ │ │ ├── MetricApiExpectTest.java │ │ │ │ └── MetricApiLiveTest.java │ │ │ ├── internal/ │ │ │ │ ├── BaseCloudWatchApiExpectTest.java │ │ │ │ ├── BaseCloudWatchApiLiveTest.java │ │ │ │ └── BaseCloudWatchExpectTest.java │ │ │ ├── options/ │ │ │ │ ├── GetMetricStatisticsOptionsTest.java │ │ │ │ ├── ListAlarmHistoryOptionsTest.java │ │ │ │ ├── ListAlarmsForMetricTest.java │ │ │ │ ├── ListAlarmsOptionsTest.java │ │ │ │ └── SaveAlarmOptionsTest.java │ │ │ └── xml/ │ │ │ ├── GetMetricStatisticsResponseHandlerTest.java │ │ │ ├── ListAlarmHistoryResponseHandlerTest.java │ │ │ ├── ListAlarmsForMetricResponseHandlerTest.java │ │ │ └── ListAlarmsResponseHandlerTest.java │ │ └── resources/ │ │ ├── DescribeAlarmHistoryResponse.xml │ │ ├── DescribeAlarmsForMetricResponse.xml │ │ ├── DescribeAlarmsResponse.xml │ │ ├── InvalidFormatResponse.xml │ │ ├── LimitExceededResponse.xml │ │ ├── VoidResponse.xml │ │ ├── get_metric_statistics.xml │ │ ├── list_metrics.xml │ │ ├── list_metrics_marker.xml │ │ └── log4j.xml │ ├── docker/ │ │ ├── README.md │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── docker/ │ │ │ ├── DockerApi.java │ │ │ ├── DockerApiMetadata.java │ │ │ ├── compute/ │ │ │ │ ├── config/ │ │ │ │ │ ├── DockerComputeServiceContextModule.java │ │ │ │ │ └── LoginPortLookupModule.java │ │ │ │ ├── functions/ │ │ │ │ │ ├── ContainerToNodeMetadata.java │ │ │ │ │ ├── CustomLoginPortFromImage.java │ │ │ │ │ ├── ImageToImage.java │ │ │ │ │ ├── LoginPortForContainer.java │ │ │ │ │ ├── PublicPortForContainerPort.java │ │ │ │ │ └── StateToStatus.java │ │ │ │ ├── options/ │ │ │ │ │ └── DockerTemplateOptions.java │ │ │ │ └── strategy/ │ │ │ │ └── DockerComputeServiceAdapter.java │ │ │ ├── config/ │ │ │ │ ├── DockerHttpApiModule.java │ │ │ │ ├── DockerOkHttpClientSupplier.java │ │ │ │ └── DockerParserModule.java │ │ │ ├── domain/ │ │ │ │ ├── Config.java │ │ │ │ ├── Container.java │ │ │ │ ├── ContainerSummary.java │ │ │ │ ├── Exec.java │ │ │ │ ├── ExecCreateParams.java │ │ │ │ ├── ExecInspect.java │ │ │ │ ├── ExecStartParams.java │ │ │ │ ├── ExposedPorts.java │ │ │ │ ├── HostConfig.java │ │ │ │ ├── Image.java │ │ │ │ ├── ImageHistory.java │ │ │ │ ├── ImageSummary.java │ │ │ │ ├── Info.java │ │ │ │ ├── Network.java │ │ │ │ ├── NetworkSettings.java │ │ │ │ ├── Node.java │ │ │ │ ├── Port.java │ │ │ │ ├── Resource.java │ │ │ │ ├── State.java │ │ │ │ ├── StatusCode.java │ │ │ │ └── Version.java │ │ │ ├── features/ │ │ │ │ ├── ContainerApi.java │ │ │ │ ├── ImageApi.java │ │ │ │ ├── MiscApi.java │ │ │ │ └── NetworkApi.java │ │ │ ├── handlers/ │ │ │ │ └── DockerErrorHandler.java │ │ │ ├── internal/ │ │ │ │ └── NullSafeCopies.java │ │ │ ├── options/ │ │ │ │ ├── AttachOptions.java │ │ │ │ ├── BuildOptions.java │ │ │ │ ├── CommitOptions.java │ │ │ │ ├── CreateImageOptions.java │ │ │ │ ├── DeleteImageOptions.java │ │ │ │ ├── ListContainerOptions.java │ │ │ │ ├── ListImageOptions.java │ │ │ │ └── RemoveContainerOptions.java │ │ │ ├── suppliers/ │ │ │ │ ├── DockerSSLContextSupplier.java │ │ │ │ ├── DockerUntrustedSSLContextSupplier.java │ │ │ │ └── SSLContextBuilder.java │ │ │ └── util/ │ │ │ ├── DockerInputStream.java │ │ │ └── StdStreamData.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── docker/ │ │ │ ├── DockerApiMetadataTest.java │ │ │ ├── compute/ │ │ │ │ ├── BaseDockerApiLiveTest.java │ │ │ │ ├── DockerComputeServiceAdapterLiveTest.java │ │ │ │ ├── DockerComputeServiceLiveTest.java │ │ │ │ ├── SshToCustomPortLiveTest.java │ │ │ │ ├── functions/ │ │ │ │ │ ├── ContainerToNodeMetadataTest.java │ │ │ │ │ ├── CustomLoginPortFromImageTest.java │ │ │ │ │ ├── ImageToImageTest.java │ │ │ │ │ └── StateToStatusTest.java │ │ │ │ ├── options/ │ │ │ │ │ └── DockerTemplateOptionsTest.java │ │ │ │ └── strategy/ │ │ │ │ └── PredicateLocateImageByNameTest.java │ │ │ ├── config/ │ │ │ │ └── DockerParserModuleTest.java │ │ │ ├── domain/ │ │ │ │ ├── ConfigTest.java │ │ │ │ └── ContainerTest.java │ │ │ ├── features/ │ │ │ │ ├── ContainerApiLiveTest.java │ │ │ │ ├── ContainerApiMockTest.java │ │ │ │ ├── ImageApiLiveTest.java │ │ │ │ ├── ImageApiMockTest.java │ │ │ │ ├── MiscApiLiveTest.java │ │ │ │ ├── MiscApiMockTest.java │ │ │ │ ├── NetworkApiLiveTest.java │ │ │ │ └── NetworkApiMockTest.java │ │ │ ├── internal/ │ │ │ │ ├── BaseDockerMockTest.java │ │ │ │ ├── BaseDockerParseTest.java │ │ │ │ └── DockerTestUtils.java │ │ │ └── parse/ │ │ │ ├── ContainerParseTest.java │ │ │ ├── ContainerVersionMajor1Minor21.java │ │ │ ├── ContainersParseTest.java │ │ │ ├── HistoryParseTest.java │ │ │ ├── ImageParseTest.java │ │ │ ├── ImagesParseTest.java │ │ │ ├── Info2ParseTest.java │ │ │ ├── InfoParseTest.java │ │ │ ├── NetworkParseTest.java │ │ │ ├── NetworksParseTest.java │ │ │ └── VersionParseTest.java │ │ └── resources/ │ │ ├── Dockerfile │ │ ├── SimpleDockerfile │ │ ├── cert.pem │ │ ├── container-1.21-create.json │ │ ├── container-1.21-inspect.json │ │ ├── container-creation.json │ │ ├── container.json │ │ ├── containers.json │ │ ├── exec.json │ │ ├── exec.start │ │ ├── execInspect.json │ │ ├── history-apiver22.json │ │ ├── history.json │ │ ├── image.json │ │ ├── images.json │ │ ├── info.json │ │ ├── info2.json │ │ ├── key.pem │ │ ├── logback.xml │ │ ├── network-creation.json │ │ ├── network.json │ │ ├── networks.json │ │ └── version.json │ ├── ec2/ │ │ ├── README.txt │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── ec2/ │ │ │ ├── EC2Api.java │ │ │ ├── EC2ApiMetadata.java │ │ │ ├── EC2Fallbacks.java │ │ │ ├── binders/ │ │ │ │ ├── BindBlockDeviceMappingToIndexedFormParams.java │ │ │ │ ├── BindBundleIdsToIndexedFormParams.java │ │ │ │ ├── BindFiltersToIndexedFormParams.java │ │ │ │ ├── BindGroupIdsToIndexedFormParams.java │ │ │ │ ├── BindGroupNamesToIndexedFormParams.java │ │ │ │ ├── BindInstanceIdsToIndexedFormParams.java │ │ │ │ ├── BindIpPermissionToIndexedFormParams.java │ │ │ │ ├── BindIpPermissionsToIndexedFormParams.java │ │ │ │ ├── BindKeyNamesToIndexedFormParams.java │ │ │ │ ├── BindProductCodesToIndexedFormParams.java │ │ │ │ ├── BindPublicIpsToIndexedFormParams.java │ │ │ │ ├── BindResourceIdsToIndexedFormParams.java │ │ │ │ ├── BindS3UploadPolicyAndSignature.java │ │ │ │ ├── BindSubnetIdsToIndexedFormParams.java │ │ │ │ ├── BindTagKeysToIndexedFormParams.java │ │ │ │ ├── BindTagsToIndexedFormParams.java │ │ │ │ ├── BindUserGroupsToIndexedFormParams.java │ │ │ │ ├── BindUserIdGroupPairToSourceSecurityGroupFormParams.java │ │ │ │ ├── BindUserIdsToIndexedFormParams.java │ │ │ │ ├── BindVolumeIdsToIndexedFormParams.java │ │ │ │ └── IfNotNullBindAvailabilityZoneToFormParam.java │ │ │ ├── compute/ │ │ │ │ ├── EC2ComputeService.java │ │ │ │ ├── EC2ComputeServiceContext.java │ │ │ │ ├── config/ │ │ │ │ │ ├── EC2BindComputeStrategiesByClass.java │ │ │ │ │ ├── EC2BindComputeSuppliersByClass.java │ │ │ │ │ ├── EC2ComputeServiceContextModule.java │ │ │ │ │ ├── EC2ComputeServiceDependenciesModule.java │ │ │ │ │ └── EC2ResolveImagesModule.java │ │ │ │ ├── domain/ │ │ │ │ │ ├── EC2HardwareBuilder.java │ │ │ │ │ ├── PasswordDataAndPrivateKey.java │ │ │ │ │ ├── RegionAndName.java │ │ │ │ │ └── RegionNameAndIngressRules.java │ │ │ │ ├── extensions/ │ │ │ │ │ ├── EC2ImageExtension.java │ │ │ │ │ └── EC2SecurityGroupExtension.java │ │ │ │ ├── functions/ │ │ │ │ │ ├── AddElasticIpsToNodemetadata.java │ │ │ │ │ ├── CreateUniqueKeyPair.java │ │ │ │ │ ├── CredentialsForInstance.java │ │ │ │ │ ├── EC2ImageParser.java │ │ │ │ │ ├── EC2SecurityGroupIdFromName.java │ │ │ │ │ ├── EC2SecurityGroupToSecurityGroup.java │ │ │ │ │ ├── ImagesToRegionAndIdMap.java │ │ │ │ │ ├── PasswordCredentialsFromWindowsInstance.java │ │ │ │ │ ├── PresentInstances.java │ │ │ │ │ ├── RunningInstanceToNodeMetadata.java │ │ │ │ │ └── WindowsLoginCredentialsFromEncryptedData.java │ │ │ │ ├── internal/ │ │ │ │ │ ├── EC2ComputeServiceContextImpl.java │ │ │ │ │ └── EC2TemplateBuilderImpl.java │ │ │ │ ├── loaders/ │ │ │ │ │ ├── CreateSecurityGroupIfNeeded.java │ │ │ │ │ ├── LoadAllocationIdForInstanceOrNull.java │ │ │ │ │ ├── LoadPublicIpForInstanceOrNull.java │ │ │ │ │ └── RegionAndIdToImage.java │ │ │ │ ├── options/ │ │ │ │ │ └── EC2TemplateOptions.java │ │ │ │ ├── predicates/ │ │ │ │ │ ├── EC2ImagePredicates.java │ │ │ │ │ └── SecurityGroupPresent.java │ │ │ │ ├── strategy/ │ │ │ │ │ ├── CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.java │ │ │ │ │ ├── DescribeImagesParallel.java │ │ │ │ │ ├── EC2CreateNodesInGroupThenAddToSet.java │ │ │ │ │ ├── EC2DestroyNodeStrategy.java │ │ │ │ │ ├── EC2GetImageStrategy.java │ │ │ │ │ ├── EC2GetNodeMetadataStrategy.java │ │ │ │ │ ├── EC2ListNodesStrategy.java │ │ │ │ │ ├── EC2PopulateDefaultLoginCredentialsForImageStrategy.java │ │ │ │ │ ├── EC2RebootNodeStrategy.java │ │ │ │ │ ├── EC2ResumeNodeStrategy.java │ │ │ │ │ ├── EC2SuspendNodeStrategy.java │ │ │ │ │ └── ReviseParsedImage.java │ │ │ │ ├── suppliers/ │ │ │ │ │ ├── EC2HardwareSupplier.java │ │ │ │ │ ├── EC2ImageSupplier.java │ │ │ │ │ └── RegionAndNameToImageSupplier.java │ │ │ │ └── util/ │ │ │ │ └── EC2ComputeUtils.java │ │ │ ├── config/ │ │ │ │ ├── BaseEC2HttpApiModule.java │ │ │ │ └── EC2HttpApiModule.java │ │ │ ├── domain/ │ │ │ │ ├── Attachment.java │ │ │ │ ├── AvailabilityZoneInfo.java │ │ │ │ ├── BlockDevice.java │ │ │ │ ├── BlockDeviceMapping.java │ │ │ │ ├── BundleInstanceS3Storage.java │ │ │ │ ├── BundleTask.java │ │ │ │ ├── Hypervisor.java │ │ │ │ ├── Image.java │ │ │ │ ├── ImageAttribute.java │ │ │ │ ├── InstanceState.java │ │ │ │ ├── InstanceStateChange.java │ │ │ │ ├── InstanceType.java │ │ │ │ ├── KeyPair.java │ │ │ │ ├── PasswordData.java │ │ │ │ ├── Permission.java │ │ │ │ ├── PublicIpInstanceIdPair.java │ │ │ │ ├── Reservation.java │ │ │ │ ├── ReservedInstancesOffering.java │ │ │ │ ├── RootDeviceType.java │ │ │ │ ├── RunningInstance.java │ │ │ │ ├── SecurityGroup.java │ │ │ │ ├── Snapshot.java │ │ │ │ ├── Subnet.java │ │ │ │ ├── Tag.java │ │ │ │ ├── UserIdGroupPair.java │ │ │ │ ├── VirtualizationType.java │ │ │ │ └── Volume.java │ │ │ ├── features/ │ │ │ │ ├── AMIApi.java │ │ │ │ ├── AvailabilityZoneAndRegionApi.java │ │ │ │ ├── ElasticBlockStoreApi.java │ │ │ │ ├── ElasticIPAddressApi.java │ │ │ │ ├── InstanceApi.java │ │ │ │ ├── KeyPairApi.java │ │ │ │ ├── SecurityGroupApi.java │ │ │ │ ├── SubnetApi.java │ │ │ │ ├── TagApi.java │ │ │ │ └── WindowsApi.java │ │ │ ├── functions/ │ │ │ │ ├── ConvertUnencodedBytesToBase64EncodedString.java │ │ │ │ └── EncodedRSAPublicKeyToBase64.java │ │ │ ├── options/ │ │ │ │ ├── BundleInstanceS3StorageOptions.java │ │ │ │ ├── CreateImageOptions.java │ │ │ │ ├── CreateSnapshotOptions.java │ │ │ │ ├── CreateVolumeOptions.java │ │ │ │ ├── DescribeAvailabilityZonesOptions.java │ │ │ │ ├── DescribeImagesOptions.java │ │ │ │ ├── DescribeRegionsOptions.java │ │ │ │ ├── DescribeSnapshotsOptions.java │ │ │ │ ├── DetachVolumeOptions.java │ │ │ │ ├── RegisterImageBackedByEbsOptions.java │ │ │ │ ├── RegisterImageOptions.java │ │ │ │ ├── RunInstancesOptions.java │ │ │ │ └── internal/ │ │ │ │ └── BaseEC2RequestOptions.java │ │ │ ├── predicates/ │ │ │ │ ├── InstanceHasIpAddress.java │ │ │ │ ├── InstanceStateRunning.java │ │ │ │ ├── InstanceStateStopped.java │ │ │ │ ├── InstanceStateTerminated.java │ │ │ │ ├── SnapshotCompleted.java │ │ │ │ ├── VolumeAttached.java │ │ │ │ ├── VolumeAvailable.java │ │ │ │ └── VolumeDetached.java │ │ │ ├── reference/ │ │ │ │ └── EC2Constants.java │ │ │ ├── suppliers/ │ │ │ │ ├── DescribeAvailabilityZonesInRegion.java │ │ │ │ └── DescribeRegionsForRegionURIs.java │ │ │ ├── util/ │ │ │ │ ├── IpPermissions.java │ │ │ │ ├── SubnetFilterBuilder.java │ │ │ │ ├── TagFilterBuilder.java │ │ │ │ └── Tags.java │ │ │ └── xml/ │ │ │ ├── AllocateAddressResponseHandler.java │ │ │ ├── AttachmentHandler.java │ │ │ ├── BaseReservationHandler.java │ │ │ ├── BlockDeviceMappingHandler.java │ │ │ ├── BooleanValueHandler.java │ │ │ ├── BundleTaskHandler.java │ │ │ ├── CreateVolumeResponseHandler.java │ │ │ ├── DescribeAddressesResponseHandler.java │ │ │ ├── DescribeAvailabilityZonesResponseHandler.java │ │ │ ├── DescribeBundleTasksResponseHandler.java │ │ │ ├── DescribeImagesResponseHandler.java │ │ │ ├── DescribeInstancesResponseHandler.java │ │ │ ├── DescribeKeyPairsResponseHandler.java │ │ │ ├── DescribeRegionsResponseHandler.java │ │ │ ├── DescribeSecurityGroupsResponseHandler.java │ │ │ ├── DescribeSnapshotsResponseHandler.java │ │ │ ├── DescribeSubnetsResponseHandler.java │ │ │ ├── DescribeTagsResponseHandler.java │ │ │ ├── DescribeVolumesResponseHandler.java │ │ │ ├── GetConsoleOutputResponseHandler.java │ │ │ ├── GetPasswordDataResponseHandler.java │ │ │ ├── ImageIdHandler.java │ │ │ ├── InstanceInitiatedShutdownBehaviorHandler.java │ │ │ ├── InstanceStateChangeHandler.java │ │ │ ├── InstanceTypeHandler.java │ │ │ ├── IpPermissionHandler.java │ │ │ ├── KeyPairResponseHandler.java │ │ │ ├── PermissionHandler.java │ │ │ ├── RunInstancesResponseHandler.java │ │ │ ├── SecurityGroupHandler.java │ │ │ ├── SnapshotHandler.java │ │ │ ├── StringValueHandler.java │ │ │ ├── SubnetHandler.java │ │ │ ├── TagHandler.java │ │ │ ├── TagSetHandler.java │ │ │ └── UnencodeStringValueHandler.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── ec2/ │ │ │ ├── CloudApplicationArchitecturesEC2ApiLiveTest.java │ │ │ ├── EBSBootEC2ApiLiveTest.java │ │ │ ├── EC2ApiMetadataTest.java │ │ │ ├── EC2ContextBuilderText.java │ │ │ ├── binders/ │ │ │ │ ├── BindBlockDeviceMappingToIndexedFormParamsTest.java │ │ │ │ ├── BindBundleIdsToIndexedFormParamsTest.java │ │ │ │ ├── BindFiltersToIndexedFormParamsTest.java │ │ │ │ ├── BindGroupNamesToIndexedFormParamsTest.java │ │ │ │ ├── BindInstanceIdsToIndexedFormParamsTest.java │ │ │ │ ├── BindKeyNamesToIndexedFormParamsTest.java │ │ │ │ ├── BindProductCodesToIndexedFormParamsTest.java │ │ │ │ ├── BindPublicIpsToIndexedFormParamsTest.java │ │ │ │ ├── BindResourceIdsToIndexedFormParamsTest.java │ │ │ │ ├── BindS3UploadPolicyAndSignatureTest.java │ │ │ │ ├── BindTagKeysToIndexedFormParamsTest.java │ │ │ │ ├── BindTagsToIndexedFormParamsTest.java │ │ │ │ ├── BindUserGroupsToIndexedFormParamsTest.java │ │ │ │ ├── BindUserIdGroupPairToSourceSecurityGroupFormParamsTest.java │ │ │ │ ├── BindUserIdsToIndexedFormParamsTest.java │ │ │ │ ├── BindVolumeIdsToIndexedFormParamsTest.java │ │ │ │ └── IfNotNullBindAvailabilityZoneToFormParamTest.java │ │ │ ├── compute/ │ │ │ │ ├── EC2ComputeServiceExpectTest.java │ │ │ │ ├── EC2ComputeServiceLiveTest.java │ │ │ │ ├── EC2TemplateBuilderLiveTest.java │ │ │ │ ├── EC2TemplateBuilderTest.java │ │ │ │ ├── TestCanRecreateGroupLiveTest.java │ │ │ │ ├── config/ │ │ │ │ │ └── EC2ComputeServiceContextModuleTest.java │ │ │ │ ├── extensions/ │ │ │ │ │ ├── EC2ImageExtensionExpectTest.java │ │ │ │ │ ├── EC2ImageExtensionLiveTest.java │ │ │ │ │ ├── EC2SecurityGroupExtensionExpectTest.java │ │ │ │ │ └── EC2SecurityGroupExtensionLiveTest.java │ │ │ │ ├── functions/ │ │ │ │ │ ├── AddElasticIpsToNodemetadataTest.java │ │ │ │ │ ├── CreateUniqueKeyPairTest.java │ │ │ │ │ ├── EC2ImageParserTest.java │ │ │ │ │ ├── EC2SecurityGroupToSecurityGroupTest.java │ │ │ │ │ ├── PresentInstancesTest.java │ │ │ │ │ ├── RunningInstanceToNodeMetadataTest.java │ │ │ │ │ └── WindowsLoginCredentialsFromEncryptedDataTest.java │ │ │ │ ├── internal/ │ │ │ │ │ ├── BaseEC2ComputeServiceContextExpectTest.java │ │ │ │ │ ├── BaseEC2ComputeServiceExpectTest.java │ │ │ │ │ └── EC2TemplateBuilderImplTest.java │ │ │ │ ├── loaders/ │ │ │ │ │ ├── CreateSecurityGroupIfNeededTest.java │ │ │ │ │ ├── LoadPublicIpForInstanceOrNullTest.java │ │ │ │ │ └── RegionAndIdToImageTest.java │ │ │ │ ├── options/ │ │ │ │ │ └── EC2TemplateOptionsTest.java │ │ │ │ └── strategy/ │ │ │ │ ├── CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptionsTest.java │ │ │ │ ├── EC2CreateNodesInGroupThenAddToSetTest.java │ │ │ │ └── EC2DestroyNodeStrategyTest.java │ │ │ ├── config/ │ │ │ │ └── EC2HttpApiModuleExpectTest.java │ │ │ ├── features/ │ │ │ │ ├── AMIApiExpectTest.java │ │ │ │ ├── AMIApiLiveTest.java │ │ │ │ ├── AMIApiTest.java │ │ │ │ ├── AvailabilityZoneAndRegionApiLiveTest.java │ │ │ │ ├── AvailabilityZoneAndRegionApiTest.java │ │ │ │ ├── BaseEC2ApiTest.java │ │ │ │ ├── EC2ElasticBlockStoreApiExpectTest.java │ │ │ │ ├── ElasticBlockStoreApiLiveTest.java │ │ │ │ ├── ElasticBlockStoreApiTest.java │ │ │ │ ├── ElasticIPAddressApiExpectTest.java │ │ │ │ ├── ElasticIPAddressApiLiveTest.java │ │ │ │ ├── ElasticIPAddressApiTest.java │ │ │ │ ├── InstanceApiExpectTest.java │ │ │ │ ├── InstanceApiLiveTest.java │ │ │ │ ├── InstanceApiTest.java │ │ │ │ ├── KeyPairApiExpectTest.java │ │ │ │ ├── KeyPairApiLiveTest.java │ │ │ │ ├── KeyPairApiTest.java │ │ │ │ ├── SecurityGroupApiExpectTest.java │ │ │ │ ├── SecurityGroupApiLiveTest.java │ │ │ │ ├── SecurityGroupApiTest.java │ │ │ │ ├── SubnetApiExpectTest.java │ │ │ │ ├── SubnetApiLiveTest.java │ │ │ │ ├── TagApiExpectTest.java │ │ │ │ ├── WindowsApiExpectTest.java │ │ │ │ ├── WindowsApiLiveTest.java │ │ │ │ ├── WindowsApiTest.java │ │ │ │ └── internal/ │ │ │ │ └── BaseTagApiLiveTest.java │ │ │ ├── functions/ │ │ │ │ ├── ConvertUnencodedBytesToBase64EncodedStringTest.java │ │ │ │ └── EncodedRSAPublicKeyToBase64Test.java │ │ │ ├── internal/ │ │ │ │ ├── BaseEC2ApiExpectTest.java │ │ │ │ ├── BaseEC2ApiLiveTest.java │ │ │ │ ├── BaseEC2ApiMockTest.java │ │ │ │ └── BaseEC2ExpectTest.java │ │ │ ├── options/ │ │ │ │ ├── BundleInstanceS3StorageOptionsTest.java │ │ │ │ ├── CreateImageOptionsTest.java │ │ │ │ ├── CreateSnapshotOptionsTest.java │ │ │ │ ├── CreateVolumeOptionsTest.java │ │ │ │ ├── DescribeImagesOptionsTest.java │ │ │ │ ├── DescribeSnapshotsOptionsTest.java │ │ │ │ ├── DetachVolumeOptionsTest.java │ │ │ │ ├── RegisterImageBackedByEbsOptionsTest.java │ │ │ │ ├── RegisterImageOptionsTest.java │ │ │ │ └── RunInstancesOptionsTest.java │ │ │ ├── parse/ │ │ │ │ ├── DescribeSubnetsResponseTest.java │ │ │ │ ├── DescribeTagsResponseTest.java │ │ │ │ └── GetPasswordDataResponseTest.java │ │ │ ├── predicates/ │ │ │ │ └── VolumeDetachedTest.java │ │ │ ├── suppliers/ │ │ │ │ ├── DescribeAvailabilityZonesInRegionMockTest.java │ │ │ │ └── DescribeRegionsForRegionURIsMockTest.java │ │ │ ├── util/ │ │ │ │ ├── IpPermissionsTest.java │ │ │ │ └── TagsTest.java │ │ │ └── xml/ │ │ │ ├── AllocateAddressResponseHandlerTest.java │ │ │ ├── AttachmentHandlerTest.java │ │ │ ├── BaseEC2HandlerTest.java │ │ │ ├── BlockDeviceMappingHandlerTest.java │ │ │ ├── BundleTaskHandlerTest.java │ │ │ ├── CreateVolumeResponseHandlerTest.java │ │ │ ├── DescribeAddressesResponseHandlerTest.java │ │ │ ├── DescribeAvailabilityZonesResponseHandlerTest.java │ │ │ ├── DescribeBundleTasksResponseHandlerTest.java │ │ │ ├── DescribeImagesResponseHandlerTest.java │ │ │ ├── DescribeInstanceAttributeTest.java │ │ │ ├── DescribeInstancesResponseHandlerTest.java │ │ │ ├── DescribeKeyPairsResponseHandlerTest.java │ │ │ ├── DescribeRegionsResponseHandlerTest.java │ │ │ ├── DescribeSecurityGroupsResponseHandlerTest.java │ │ │ ├── DescribeSnapshotsResponseHandlerTest.java │ │ │ ├── DescribeVolumesResponseHandlerTest.java │ │ │ ├── GetConsoleOutputResponseHandlerTest.java │ │ │ ├── InstanceStateChangeHandlerTest.java │ │ │ ├── KeyPairResponseHandlerTest.java │ │ │ ├── PermissionHandlerTest.java │ │ │ ├── RunInstancesResponseHandlerTest.java │ │ │ └── SnapshotHandlerTest.java │ │ └── resources/ │ │ ├── allocate_address.xml │ │ ├── amzn_images.xml │ │ ├── attach.xml │ │ ├── authorize_securitygroup_ingress_response.xml │ │ ├── availabilityZones-ap-northeast-1.xml │ │ ├── availabilityZones-ap-southeast-1.xml │ │ ├── availabilityZones-eu-west-1.xml │ │ ├── availabilityZones-sa-east-1.xml │ │ ├── availabilityZones-us-east-1.xml │ │ ├── availabilityZones-us-west-1.xml │ │ ├── availabilityZones-us-west-2.xml │ │ ├── availabilityZones.xml │ │ ├── bundle_instance.xml │ │ ├── cancel_bundle_task.xml │ │ ├── create_keypair.xml │ │ ├── created_securitygroup.xml │ │ ├── created_snapshot.xml │ │ ├── created_volume.xml │ │ ├── delete_keypair.xml │ │ ├── delete_placementgroup.xml │ │ ├── delete_securitygroup.xml │ │ ├── describe_addresses.xml │ │ ├── describe_addresses_single.xml │ │ ├── describe_addresses_with_tags.xml │ │ ├── describe_bundle_tasks.xml │ │ ├── describe_image_attribute_blockDeviceMapping.xml │ │ ├── describe_image_attribute_launchPermission.xml │ │ ├── describe_images.xml │ │ ├── describe_images_ebs.xml │ │ ├── describe_images_imageextension0.xml │ │ ├── describe_images_imageextension1.xml │ │ ├── describe_images_imageextension2.xml │ │ ├── describe_images_nova.xml │ │ ├── describe_images_tags.xml │ │ ├── describe_images_windows.xml │ │ ├── describe_instances.xml │ │ ├── describe_instances_ebs.xml │ │ ├── describe_instances_empty.xml │ │ ├── describe_instances_multiple.xml │ │ ├── describe_instances_running-1.xml │ │ ├── describe_instances_running-named.xml │ │ ├── describe_instances_running.xml │ │ ├── describe_instances_running_securitygroups.xml │ │ ├── describe_instances_three_ids.xml │ │ ├── describe_keypairs.xml │ │ ├── describe_keypairs_jcloudssingle.xml │ │ ├── describe_securitygroups.xml │ │ ├── describe_securitygroups_empty.xml │ │ ├── describe_securitygroups_extension_cidr.xml │ │ ├── describe_securitygroups_extension_group.xml │ │ ├── describe_securitygroups_extension_new.xml │ │ ├── describe_securitygroups_extension_single.xml │ │ ├── describe_snapshots.xml │ │ ├── describe_subnets.xml │ │ ├── describe_tags.xml │ │ ├── describe_volumes.xml │ │ ├── describe_volumes_single.xml │ │ ├── disableApiTermination.xml │ │ ├── get_console_output_response.xml │ │ ├── get_passworddata.xml │ │ ├── instanceInitiatedShutdownBehavior.xml │ │ ├── instanceType.xml │ │ ├── log4j.xml │ │ ├── new_instance.xml │ │ ├── new_securitygroup.xml │ │ ├── ramdisk.xml │ │ ├── regionEndpoints-additional.xml │ │ ├── regionEndpoints-all.xml │ │ ├── regionEndpoints.xml │ │ ├── run_instances.xml │ │ ├── run_instances_cloudbridge.xml │ │ ├── run_instances_three.xml │ │ ├── start_instances.xml │ │ ├── stop_instances.xml │ │ ├── terminate_instances.xml │ │ └── userData.xml │ ├── elasticstack/ │ │ ├── README.txt │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── elasticstack/ │ │ │ ├── ElasticStackApi.java │ │ │ ├── ElasticStackApiMetadata.java │ │ │ ├── binders/ │ │ │ │ ├── BindDriveDataToPlainTextString.java │ │ │ │ ├── BindDriveToPlainTextString.java │ │ │ │ └── BindServerToPlainTextString.java │ │ │ ├── compute/ │ │ │ │ ├── ElasticStackComputeServiceAdapter.java │ │ │ │ ├── config/ │ │ │ │ │ └── ElasticStackComputeServiceContextModule.java │ │ │ │ └── functions/ │ │ │ │ ├── ServerInfoToNodeMetadata.java │ │ │ │ ├── StandardDriveToWellKnownImage.java │ │ │ │ └── WellKnownImageToImage.java │ │ │ ├── config/ │ │ │ │ └── ElasticStackHttpApiModule.java │ │ │ ├── domain/ │ │ │ │ ├── BlockDevice.java │ │ │ │ ├── ClaimType.java │ │ │ │ ├── CreateDriveRequest.java │ │ │ │ ├── Device.java │ │ │ │ ├── Drive.java │ │ │ │ ├── DriveData.java │ │ │ │ ├── DriveInfo.java │ │ │ │ ├── DriveMetrics.java │ │ │ │ ├── DriveStatus.java │ │ │ │ ├── IDEDevice.java │ │ │ │ ├── ImageConversionType.java │ │ │ │ ├── Item.java │ │ │ │ ├── MediaType.java │ │ │ │ ├── Model.java │ │ │ │ ├── NIC.java │ │ │ │ ├── SCSIDevice.java │ │ │ │ ├── Server.java │ │ │ │ ├── ServerInfo.java │ │ │ │ ├── ServerMetrics.java │ │ │ │ ├── ServerStatus.java │ │ │ │ ├── StandardDrive.java │ │ │ │ ├── VNC.java │ │ │ │ └── WellKnownImage.java │ │ │ ├── functions/ │ │ │ │ ├── BaseDriveToMap.java │ │ │ │ ├── CreateDriveRequestToMap.java │ │ │ │ ├── DriveDataToMap.java │ │ │ │ ├── KeyValuesDelimitedByBlankLinesToDriveInfo.java │ │ │ │ ├── KeyValuesDelimitedByBlankLinesToServerInfo.java │ │ │ │ ├── ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSet.java │ │ │ │ ├── ListOfKeyValuesDelimitedByBlankLinesToListOfMaps.java │ │ │ │ ├── ListOfKeyValuesDelimitedByBlankLinesToServerInfoSet.java │ │ │ │ ├── ListOfKeyValuesDelimitedByBlankLinesToStandardDriveSet.java │ │ │ │ ├── ListOfMapsToListOfKeyValuesDelimitedByBlankLines.java │ │ │ │ ├── MapToDevices.java │ │ │ │ ├── MapToDriveInfo.java │ │ │ │ ├── MapToDriveMetrics.java │ │ │ │ ├── MapToNICs.java │ │ │ │ ├── MapToServerInfo.java │ │ │ │ ├── MapToServerMetrics.java │ │ │ │ ├── MapToStandardDrive.java │ │ │ │ ├── ReturnPayload.java │ │ │ │ ├── ServerToMap.java │ │ │ │ └── SplitNewlines.java │ │ │ ├── handlers/ │ │ │ │ └── ElasticStackErrorHandler.java │ │ │ ├── predicates/ │ │ │ │ └── DriveClaimed.java │ │ │ ├── reference/ │ │ │ │ └── ElasticStackConstants.java │ │ │ ├── suppliers/ │ │ │ │ ├── StandardDiskImageSupplier.java │ │ │ │ └── WellKnownImageSupplier.java │ │ │ └── util/ │ │ │ └── Servers.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── elasticstack/ │ │ │ ├── ElasticStackApiLiveTest.java │ │ │ ├── ElasticStackApiMetadataTest.java │ │ │ ├── ElasticStackApiTest.java │ │ │ ├── ElasticStackMockTest.java │ │ │ ├── binders/ │ │ │ │ ├── BindDriveDataToPlainTextStringTest.java │ │ │ │ ├── BindDriveToPlainTextStringTest.java │ │ │ │ └── BindServerToPlainTextStringTest.java │ │ │ ├── compute/ │ │ │ │ ├── ElasticStackComputeServiceAdapterTest.java │ │ │ │ ├── ElasticStackComputeServiceLiveTest.java │ │ │ │ └── functions/ │ │ │ │ ├── GetImageIdFromServerTest.java │ │ │ │ └── StandardDriveToWellKnownImageTest.java │ │ │ ├── functions/ │ │ │ │ ├── BaseDriveToMapTest.java │ │ │ │ ├── CreateDriveRequestToMapTest.java │ │ │ │ ├── DriveDataToMapTest.java │ │ │ │ ├── KeyValuesDelimitedByBlankLinesToDriveInfoTest.java │ │ │ │ ├── KeyValuesDelimitedByBlankLinesToServerInfoTest.java │ │ │ │ ├── ListOfKeyValuesDelimitedByBlankLinesToDriveInfoSetTest.java │ │ │ │ ├── ListOfKeyValuesDelimitedByBlankLinesToListOfMapsTest.java │ │ │ │ ├── ListOfKeyValuesDelimitedByBlankLinesToServerInfoSetTest.java │ │ │ │ ├── ListOfKeyValuesDelimitedByBlankLinesToStandardDriveSetTest.java │ │ │ │ ├── ListOfMapsToListOfKeyValuesDelimitedByBlankLinesTest.java │ │ │ │ ├── MapToDriveInfoTest.java │ │ │ │ ├── MapToServerInfoTest.java │ │ │ │ ├── MapToStandardDriveTest.java │ │ │ │ ├── ServerToMapTest.java │ │ │ │ └── SplitNewlinesTest.java │ │ │ ├── handlers/ │ │ │ │ └── ElasticStackErrorHandlerTest.java │ │ │ └── suppliers/ │ │ │ └── MockStandardDiskImageSupplier.java │ │ └── resources/ │ │ ├── create_drive.txt │ │ ├── create_server.txt │ │ ├── drive.txt │ │ ├── drive_data.txt │ │ ├── log4j.xml │ │ ├── new_server.txt │ │ ├── new_server2.txt │ │ ├── server2.txt │ │ ├── servers.txt │ │ ├── standard_drive.txt │ │ ├── standard_drives.txt │ │ ├── standard_drives_uuids.txt │ │ └── uuids.txt │ ├── filesystem/ │ │ ├── README.txt │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── filesystem/ │ │ │ ├── FilesystemApiMetadata.java │ │ │ ├── config/ │ │ │ │ └── FilesystemBlobStoreContextModule.java │ │ │ ├── predicates/ │ │ │ │ └── validators/ │ │ │ │ ├── FilesystemBlobKeyValidator.java │ │ │ │ ├── FilesystemContainerNameValidator.java │ │ │ │ └── internal/ │ │ │ │ ├── FilesystemBlobKeyValidatorImpl.java │ │ │ │ └── FilesystemContainerNameValidatorImpl.java │ │ │ ├── reference/ │ │ │ │ └── FilesystemConstants.java │ │ │ ├── strategy/ │ │ │ │ └── internal/ │ │ │ │ └── FilesystemStorageStrategyImpl.java │ │ │ └── util/ │ │ │ ├── Utils.java │ │ │ └── internal/ │ │ │ └── FileSystemBlobUtilsImpl.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── filesystem/ │ │ │ ├── FilesystemApiMetadataTest.java │ │ │ ├── FilesystemBlobStoreTest.java │ │ │ ├── integration/ │ │ │ │ ├── FilesystemBlobIntegrationTest.java │ │ │ │ ├── FilesystemContainerIntegrationTest.java │ │ │ │ └── FilesystemServiceIntegrationTest.java │ │ │ ├── predicates/ │ │ │ │ └── validators/ │ │ │ │ └── internal/ │ │ │ │ ├── FilesystemBlobKeyValidatorTest.java │ │ │ │ └── FilesystemContainerNameValidatorTest.java │ │ │ ├── strategy/ │ │ │ │ └── internal/ │ │ │ │ └── FilesystemStorageStrategyImplTest.java │ │ │ └── utils/ │ │ │ └── TestUtils.java │ │ └── resources/ │ │ └── logging.properties │ ├── glacier/ │ │ ├── README.md │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── glacier/ │ │ │ ├── GlacierApiMetadata.java │ │ │ ├── GlacierClient.java │ │ │ ├── GlacierResponseException.java │ │ │ ├── binders/ │ │ │ │ ├── BindArchiveOutputRangeToHeaders.java │ │ │ │ ├── BindArchiveSizeToHeaders.java │ │ │ │ ├── BindContentRangeToHeaders.java │ │ │ │ ├── BindDescriptionToHeaders.java │ │ │ │ ├── BindHashesToHeaders.java │ │ │ │ ├── BindJobRequestToJsonPayload.java │ │ │ │ ├── BindMultipartTreeHashToHeaders.java │ │ │ │ └── BindPartSizeToHeaders.java │ │ │ ├── blobstore/ │ │ │ │ ├── GlacierBlobStore.java │ │ │ │ ├── config/ │ │ │ │ │ └── GlacierBlobStoreContextModule.java │ │ │ │ ├── functions/ │ │ │ │ │ ├── ArchiveMetadataCollectionToStorageMetadata.java │ │ │ │ │ ├── ListContainerOptionsToInventoryRetrievalJobRequest.java │ │ │ │ │ ├── PaginatedVaultCollectionToStorageMetadata.java │ │ │ │ │ └── VaultMetadataToStorageMetadata.java │ │ │ │ └── strategy/ │ │ │ │ ├── MultipartUploadStrategy.java │ │ │ │ ├── PayloadSlice.java │ │ │ │ ├── PollingStrategy.java │ │ │ │ ├── SlicingStrategy.java │ │ │ │ └── internal/ │ │ │ │ ├── BasePollingStrategy.java │ │ │ │ ├── BaseSlicingStrategy.java │ │ │ │ ├── ClearVaultStrategy.java │ │ │ │ └── SequentialMultipartUploadStrategy.java │ │ │ ├── config/ │ │ │ │ ├── GlacierHttpApiModule.java │ │ │ │ └── GlacierParserModule.java │ │ │ ├── domain/ │ │ │ │ ├── ArchiveMetadata.java │ │ │ │ ├── ArchiveMetadataCollection.java │ │ │ │ ├── ArchiveRetrievalJobRequest.java │ │ │ │ ├── GlacierError.java │ │ │ │ ├── InventoryRetrievalJobRequest.java │ │ │ │ ├── InventoryRetrievalParameters.java │ │ │ │ ├── JobMetadata.java │ │ │ │ ├── JobRequest.java │ │ │ │ ├── JobStatus.java │ │ │ │ ├── MultipartUploadMetadata.java │ │ │ │ ├── PaginatedJobCollection.java │ │ │ │ ├── PaginatedMultipartUploadCollection.java │ │ │ │ ├── PaginatedVaultCollection.java │ │ │ │ ├── PartMetadata.java │ │ │ │ └── VaultMetadata.java │ │ │ ├── fallbacks/ │ │ │ │ └── FalseOnIllegalArgumentException.java │ │ │ ├── filters/ │ │ │ │ └── RequestAuthorizeSignature.java │ │ │ ├── functions/ │ │ │ │ ├── GetPayloadFromHttpContent.java │ │ │ │ ├── ParseArchiveIdHeader.java │ │ │ │ ├── ParseArchiveMetadataCollectionFromHttpContent.java │ │ │ │ ├── ParseJobIdHeader.java │ │ │ │ ├── ParseJobMetadataFromHttpContent.java │ │ │ │ ├── ParseJobMetadataListFromHttpContent.java │ │ │ │ ├── ParseMultipartUploadIdHeader.java │ │ │ │ ├── ParseMultipartUploadListFromHttpContent.java │ │ │ │ ├── ParseMultipartUploadPartListFromHttpContent.java │ │ │ │ ├── ParseMultipartUploadTreeHashHeader.java │ │ │ │ ├── ParseVaultMetadataFromHttpContent.java │ │ │ │ └── ParseVaultMetadataListFromHttpContent.java │ │ │ ├── handlers/ │ │ │ │ └── ParseGlacierErrorFromJsonContent.java │ │ │ ├── options/ │ │ │ │ └── PaginationOptions.java │ │ │ ├── predicates/ │ │ │ │ └── validators/ │ │ │ │ ├── DescriptionValidator.java │ │ │ │ ├── PartSizeValidator.java │ │ │ │ ├── PayloadValidator.java │ │ │ │ └── VaultNameValidator.java │ │ │ ├── reference/ │ │ │ │ └── GlacierHeaders.java │ │ │ └── util/ │ │ │ ├── AWSRequestSignerV4.java │ │ │ ├── ContentRange.java │ │ │ └── TreeHash.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── glacier/ │ │ │ ├── GlacierApiMetadataTest.java │ │ │ ├── GlacierClientLiveTest.java │ │ │ ├── GlacierClientLongLiveTest.java │ │ │ ├── GlacierClientMockTest.java │ │ │ ├── blobstore/ │ │ │ │ └── strategy/ │ │ │ │ └── internal/ │ │ │ │ ├── BaseSlicingStrategyTest.java │ │ │ │ └── MultipartUploadStrategyMockTest.java │ │ │ ├── predicates/ │ │ │ │ └── validators/ │ │ │ │ ├── DescriptionValidatorTest.java │ │ │ │ ├── PartSizeValidatorTest.java │ │ │ │ ├── PayloadValidatorTest.java │ │ │ │ └── VaultNameValidatorTest.java │ │ │ └── util/ │ │ │ ├── AWSRequestSignerV4Test.java │ │ │ ├── ContentRangeTest.java │ │ │ ├── TestUtils.java │ │ │ └── TreeHashTest.java │ │ └── resources/ │ │ ├── json/ │ │ │ ├── describeJobResponseBody.json │ │ │ ├── describeVaultResponseBody.json │ │ │ ├── getJobOutputResponseBody.json │ │ │ ├── listJobsResponseBody.json │ │ │ ├── listMultipartUploadsResponseBody.json │ │ │ ├── listMultipartUploadsWithEmptyListResponseBody.json │ │ │ ├── listPartsResponseBody.json │ │ │ ├── listVaultsResponseBody.json │ │ │ ├── listVaultsWithEmptyListResponseBody.json │ │ │ └── listVaultsWithQueryParamsResponseBody.json │ │ └── testng.xml │ ├── oauth/ │ │ ├── README │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── oauth/ │ │ │ └── v2/ │ │ │ ├── AuthorizationApi.java │ │ │ ├── OAuthFallbacks.java │ │ │ ├── config/ │ │ │ │ ├── Authorization.java │ │ │ │ ├── CertificateFingerprintSupplier.java │ │ │ │ ├── CredentialType.java │ │ │ │ ├── OAuthConfigFactory.java │ │ │ │ ├── OAuthModule.java │ │ │ │ ├── OAuthProperties.java │ │ │ │ ├── OAuthScopes.java │ │ │ │ └── PrivateKeySupplier.java │ │ │ ├── domain/ │ │ │ │ ├── CertificateFingerprint.java │ │ │ │ ├── Claims.java │ │ │ │ ├── ClientCredentialsAuthArgs.java │ │ │ │ ├── ClientCredentialsClaims.java │ │ │ │ ├── ClientSecret.java │ │ │ │ └── Token.java │ │ │ ├── filters/ │ │ │ │ ├── BearerTokenFromCredentials.java │ │ │ │ ├── ClientCredentialsJWTBearerTokenFlow.java │ │ │ │ ├── ClientCredentialsSecretFlow.java │ │ │ │ ├── JWTBearerTokenFlow.java │ │ │ │ └── OAuthFilter.java │ │ │ └── functions/ │ │ │ ├── ClaimsToAssertion.java │ │ │ └── ClientCredentialsClaimsToAssertion.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── oauth/ │ │ │ └── v2/ │ │ │ ├── AuthorizationApiLiveTest.java │ │ │ ├── AuthorizationApiMockTest.java │ │ │ ├── OAuthTestUtils.java │ │ │ ├── config/ │ │ │ │ └── PrivateKeySupplierTest.java │ │ │ ├── filters/ │ │ │ │ └── TestJWTBearerTokenFlow.java │ │ │ └── functions/ │ │ │ └── ClaimsToAssertionTest.java │ │ └── resources/ │ │ ├── logback.xml │ │ ├── testcert.pem │ │ └── testpk.pem │ ├── openstack-cinder/ │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── openstack/ │ │ │ └── cinder/ │ │ │ └── v1/ │ │ │ ├── CinderApi.java │ │ │ ├── CinderApiMetadata.java │ │ │ ├── config/ │ │ │ │ ├── CinderHttpApiModule.java │ │ │ │ └── CinderParserModule.java │ │ │ ├── domain/ │ │ │ │ ├── AvailabilityZone.java │ │ │ │ ├── Snapshot.java │ │ │ │ ├── SnapshotExtendedAttributes.java │ │ │ │ ├── Volume.java │ │ │ │ ├── VolumeAttachment.java │ │ │ │ ├── VolumeQuota.java │ │ │ │ ├── VolumeType.java │ │ │ │ └── ZoneState.java │ │ │ ├── extensions/ │ │ │ │ ├── AvailabilityZoneApi.java │ │ │ │ └── ExtensionNamespaces.java │ │ │ ├── features/ │ │ │ │ ├── QuotaApi.java │ │ │ │ ├── SnapshotApi.java │ │ │ │ ├── VolumeApi.java │ │ │ │ └── VolumeTypeApi.java │ │ │ ├── handlers/ │ │ │ │ └── CinderErrorHandler.java │ │ │ ├── options/ │ │ │ │ ├── CreateSnapshotOptions.java │ │ │ │ └── CreateVolumeOptions.java │ │ │ └── predicates/ │ │ │ ├── SnapshotPredicates.java │ │ │ └── VolumePredicates.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── openstack/ │ │ │ └── cinder/ │ │ │ └── v1/ │ │ │ ├── domain/ │ │ │ │ └── VolumeTest.java │ │ │ ├── features/ │ │ │ │ ├── AvailabilityZoneApiExpectTest.java │ │ │ │ ├── AvailabilityZoneApiLiveTest.java │ │ │ │ ├── QuotasApiExpectTest.java │ │ │ │ ├── QuotasApiLiveTest.java │ │ │ │ ├── SnapshotApiExpectTest.java │ │ │ │ ├── VolumeAndSnapshotApiLiveTest.java │ │ │ │ ├── VolumeApiExpectTest.java │ │ │ │ ├── VolumeTypeApiExpectTest.java │ │ │ │ └── VolumeTypeApiLiveTest.java │ │ │ └── internal/ │ │ │ ├── BaseCinderApiExpectTest.java │ │ │ ├── BaseCinderApiLiveTest.java │ │ │ └── BaseCinderExpectTest.java │ │ └── resources/ │ │ ├── availability_zones_list.json │ │ ├── quotas.json │ │ ├── snapshot_create.json │ │ ├── snapshot_create_response.json │ │ ├── snapshot_get.json │ │ ├── snapshot_list_details.json │ │ ├── snapshot_list_simple.json │ │ ├── volume_create.json │ │ ├── volume_create_response.json │ │ ├── volume_get.json │ │ ├── volume_list_details.json │ │ ├── volume_list_simple.json │ │ ├── volume_type_get.json │ │ └── volume_type_list_simple.json │ ├── openstack-keystone/ │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── openstack/ │ │ │ ├── keystone/ │ │ │ │ ├── auth/ │ │ │ │ │ ├── AuthHeaders.java │ │ │ │ │ ├── AuthenticationApi.java │ │ │ │ │ ├── config/ │ │ │ │ │ │ ├── Authentication.java │ │ │ │ │ │ ├── AuthenticationModule.java │ │ │ │ │ │ ├── CredentialType.java │ │ │ │ │ │ └── CredentialTypes.java │ │ │ │ │ ├── domain/ │ │ │ │ │ │ ├── ApiAccessKeyCredentials.java │ │ │ │ │ │ ├── AuthInfo.java │ │ │ │ │ │ ├── PasswordCredentials.java │ │ │ │ │ │ ├── TenantOrDomainAndCredentials.java │ │ │ │ │ │ └── TokenCredentials.java │ │ │ │ │ ├── filters/ │ │ │ │ │ │ └── AuthenticateRequest.java │ │ │ │ │ ├── functions/ │ │ │ │ │ │ ├── AuthenticateApiAccessKeyCredentials.java │ │ │ │ │ │ ├── AuthenticatePasswordCredentials.java │ │ │ │ │ │ ├── AuthenticateTokenCredentials.java │ │ │ │ │ │ └── BaseAuthenticator.java │ │ │ │ │ └── handlers/ │ │ │ │ │ └── RetryOnRenew.java │ │ │ │ ├── catalog/ │ │ │ │ │ ├── ServiceEndpoint.java │ │ │ │ │ ├── config/ │ │ │ │ │ │ ├── InternalUrlModule.java │ │ │ │ │ │ ├── KeystoneAdminURLModule.java │ │ │ │ │ │ └── ServiceCatalogModule.java │ │ │ │ │ ├── functions/ │ │ │ │ │ │ ├── AdminEndpointResolutionStrategy.java │ │ │ │ │ │ ├── AdminURL.java │ │ │ │ │ │ ├── BaseEndpointResolutionStrategy.java │ │ │ │ │ │ ├── InternalURL.java │ │ │ │ │ │ ├── PublicURLOrInternal.java │ │ │ │ │ │ ├── ReturnRegionOrProvider.java │ │ │ │ │ │ ├── ServiceEndpointResolutionStrategy.java │ │ │ │ │ │ └── ServiceEndpointToRegion.java │ │ │ │ │ └── suppliers/ │ │ │ │ │ ├── LocationIdToURIFromServiceEndpointsForTypeAndVersion.java │ │ │ │ │ ├── RegionIdToAdminURIFromServiceEndpointsForTypeAndVersion.java │ │ │ │ │ ├── RegionIdToAdminURISupplier.java │ │ │ │ │ └── RegionIdToURIFromServiceEndpointsForTypeAndVersion.java │ │ │ │ ├── config/ │ │ │ │ │ └── KeystoneProperties.java │ │ │ │ ├── v2_0/ │ │ │ │ │ ├── KeystoneApi.java │ │ │ │ │ ├── KeystoneApiMetadata.java │ │ │ │ │ ├── KeystoneFallbacks.java │ │ │ │ │ ├── auth/ │ │ │ │ │ │ └── V2AuthenticationApi.java │ │ │ │ │ ├── binders/ │ │ │ │ │ │ └── BindAuthToJsonPayload.java │ │ │ │ │ ├── catalog/ │ │ │ │ │ │ └── V2ServiceCatalog.java │ │ │ │ │ ├── config/ │ │ │ │ │ │ ├── KeystoneHttpApiModule.java │ │ │ │ │ │ ├── KeystoneParserModule.java │ │ │ │ │ │ └── NamespaceAliases.java │ │ │ │ │ ├── domain/ │ │ │ │ │ │ ├── Access.java │ │ │ │ │ │ ├── ApiMetadata.java │ │ │ │ │ │ ├── Endpoint.java │ │ │ │ │ │ ├── MediaType.java │ │ │ │ │ │ ├── Role.java │ │ │ │ │ │ ├── Service.java │ │ │ │ │ │ ├── Tenant.java │ │ │ │ │ │ ├── Token.java │ │ │ │ │ │ └── User.java │ │ │ │ │ ├── extensions/ │ │ │ │ │ │ ├── ExtensionAliases.java │ │ │ │ │ │ ├── ExtensionNames.java │ │ │ │ │ │ ├── ExtensionNamespaces.java │ │ │ │ │ │ ├── RoleAdminApi.java │ │ │ │ │ │ ├── ServiceAdminApi.java │ │ │ │ │ │ ├── TenantAdminApi.java │ │ │ │ │ │ └── UserAdminApi.java │ │ │ │ │ ├── features/ │ │ │ │ │ │ ├── ServiceApi.java │ │ │ │ │ │ ├── TenantApi.java │ │ │ │ │ │ ├── TokenApi.java │ │ │ │ │ │ └── UserApi.java │ │ │ │ │ ├── functions/ │ │ │ │ │ │ └── internal/ │ │ │ │ │ │ ├── ParseServices.java │ │ │ │ │ │ ├── ParseTenants.java │ │ │ │ │ │ └── ParseUsers.java │ │ │ │ │ ├── handlers/ │ │ │ │ │ │ └── KeystoneErrorHandler.java │ │ │ │ │ └── options/ │ │ │ │ │ ├── CreateTenantOptions.java │ │ │ │ │ ├── CreateUserOptions.java │ │ │ │ │ ├── UpdateTenantOptions.java │ │ │ │ │ └── UpdateUserOptions.java │ │ │ │ └── v3/ │ │ │ │ ├── KeystoneApi.java │ │ │ │ ├── KeystoneApiMetadata.java │ │ │ │ ├── auth/ │ │ │ │ │ └── V3AuthenticationApi.java │ │ │ │ ├── binders/ │ │ │ │ │ ├── BindAccessKeyAuthToJsonPayload.java │ │ │ │ │ ├── BindAuthToJsonPayload.java │ │ │ │ │ ├── BindPasswordAuthToJsonPayload.java │ │ │ │ │ └── BindTokenAuthToJsonPayload.java │ │ │ │ ├── catalog/ │ │ │ │ │ └── V3ServiceCatalog.java │ │ │ │ ├── config/ │ │ │ │ │ └── KeystoneHttpApiModule.java │ │ │ │ ├── domain/ │ │ │ │ │ ├── Auth.java │ │ │ │ │ ├── Catalog.java │ │ │ │ │ ├── Endpoint.java │ │ │ │ │ ├── Group.java │ │ │ │ │ ├── Link.java │ │ │ │ │ ├── Project.java │ │ │ │ │ ├── Region.java │ │ │ │ │ ├── Token.java │ │ │ │ │ └── User.java │ │ │ │ ├── features/ │ │ │ │ │ ├── AuthApi.java │ │ │ │ │ ├── CatalogApi.java │ │ │ │ │ ├── ProjectApi.java │ │ │ │ │ ├── RegionApi.java │ │ │ │ │ └── UserApi.java │ │ │ │ └── parsers/ │ │ │ │ └── ParseTokenFromHttpResponse.java │ │ │ └── v2_0/ │ │ │ ├── ServiceType.java │ │ │ ├── domain/ │ │ │ │ ├── Extension.java │ │ │ │ ├── Limit.java │ │ │ │ ├── Limits.java │ │ │ │ ├── Link.java │ │ │ │ ├── PaginatedCollection.java │ │ │ │ ├── RateLimit.java │ │ │ │ └── Resource.java │ │ │ ├── features/ │ │ │ │ └── ExtensionApi.java │ │ │ ├── functions/ │ │ │ │ └── PresentWhenExtensionAnnotationMatchesExtensionSet.java │ │ │ ├── options/ │ │ │ │ └── PaginationOptions.java │ │ │ ├── predicates/ │ │ │ │ ├── ExtensionPredicates.java │ │ │ │ └── LinkPredicates.java │ │ │ └── services/ │ │ │ ├── Compute.java │ │ │ ├── Extension.java │ │ │ ├── Identity.java │ │ │ ├── Image.java │ │ │ └── ObjectStore.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── openstack/ │ │ │ ├── keystone/ │ │ │ │ ├── auth/ │ │ │ │ │ ├── config/ │ │ │ │ │ │ ├── CredentialTypesTest.java │ │ │ │ │ │ └── ProviderModuleExpectTest.java │ │ │ │ │ ├── handlers/ │ │ │ │ │ │ └── RetryOnRenewTest.java │ │ │ │ │ └── suppliers/ │ │ │ │ │ ├── LocationIdToURIFromAccessForTypeAndVersionTest.java │ │ │ │ │ ├── RegionIdToAdminURIFromAccessForTypeAndVersionTest.java │ │ │ │ │ └── RegionIdToURIFromAccessForTypeAndVersionTest.java │ │ │ │ ├── catalog/ │ │ │ │ │ └── functions/ │ │ │ │ │ ├── AdminURLTest.java │ │ │ │ │ ├── InternalURLTest.java │ │ │ │ │ ├── PublicURLOrInternalTest.java │ │ │ │ │ └── ReturnRegionOrProviderTest.java │ │ │ │ ├── v2_0/ │ │ │ │ │ ├── KeystoneApiExpectTest.java │ │ │ │ │ ├── KeystoneApiLiveTest.java │ │ │ │ │ ├── extensions/ │ │ │ │ │ │ ├── RoleAdminApiLiveTest.java │ │ │ │ │ │ ├── RoleAdminApiMockTest.java │ │ │ │ │ │ ├── ServiceAdminApiLiveTest.java │ │ │ │ │ │ ├── ServiceAdminApiMockTest.java │ │ │ │ │ │ ├── TenantAdminApiLiveTest.java │ │ │ │ │ │ ├── TenantAdminApiMockTest.java │ │ │ │ │ │ ├── UserAdminApiLiveTest.java │ │ │ │ │ │ └── UserAdminApiMockTest.java │ │ │ │ │ ├── features/ │ │ │ │ │ │ ├── ServiceApiExpectTest.java │ │ │ │ │ │ ├── ServiceApiLiveTest.java │ │ │ │ │ │ ├── TenantApiExpectTest.java │ │ │ │ │ │ ├── TenantApiLiveTest.java │ │ │ │ │ │ ├── TokenApiExpectTest.java │ │ │ │ │ │ ├── TokenApiLiveTest.java │ │ │ │ │ │ ├── UserApiExpectTest.java │ │ │ │ │ │ └── UserApiLiveTest.java │ │ │ │ │ ├── functions/ │ │ │ │ │ │ └── internal/ │ │ │ │ │ │ └── ParseUsersTest.java │ │ │ │ │ ├── internal/ │ │ │ │ │ │ ├── BaseKeystoneApiLiveTest.java │ │ │ │ │ │ ├── BaseKeystoneRestApiExpectTest.java │ │ │ │ │ │ └── KeystoneFixture.java │ │ │ │ │ └── parse/ │ │ │ │ │ ├── ParseAccessTest.java │ │ │ │ │ ├── ParseAdminAccessTest.java │ │ │ │ │ ├── ParseDevstackApiMetadataTest.java │ │ │ │ │ ├── ParseMinimalAccessTest.java │ │ │ │ │ ├── ParseRackspaceAccessTest.java │ │ │ │ │ ├── ParseRackspaceApiMetadataTest.java │ │ │ │ │ ├── ParseRackspaceCryptoTokenAccessTest.java │ │ │ │ │ └── ParseRandomEndpointVersionAccessTest.java │ │ │ │ └── v3/ │ │ │ │ ├── auth/ │ │ │ │ │ ├── V3AuthenticationApiLiveTest.java │ │ │ │ │ └── V3AuthenticationApiMockTest.java │ │ │ │ ├── features/ │ │ │ │ │ ├── AuthApiLiveTest.java │ │ │ │ │ ├── AuthApiMockTest.java │ │ │ │ │ ├── CatalogApiLiveTest.java │ │ │ │ │ ├── CatalogApiMockTest.java │ │ │ │ │ ├── ProjectApiLiveTest.java │ │ │ │ │ ├── ProjectApiMockTest.java │ │ │ │ │ ├── RegionApiLiveTest.java │ │ │ │ │ ├── RegionApiMockTest.java │ │ │ │ │ ├── UserApiLiveTest.java │ │ │ │ │ └── UserApiMockTest.java │ │ │ │ └── internal/ │ │ │ │ ├── BaseV3KeystoneApiLiveTest.java │ │ │ │ └── BaseV3KeystoneApiMockTest.java │ │ │ └── v2_0/ │ │ │ ├── functions/ │ │ │ │ └── PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSetTest.java │ │ │ ├── internal/ │ │ │ │ └── BaseOpenStackMockTest.java │ │ │ ├── options/ │ │ │ │ └── PaginationOptionsTest.java │ │ │ └── predicates/ │ │ │ ├── ExtensionPredicatesTest.java │ │ │ └── LinkPredicatesTest.java │ │ └── resources/ │ │ ├── access_minimal.json │ │ ├── access_version_uids.json │ │ ├── adminAuth.json │ │ ├── admin_extensions.json │ │ ├── devstackVersion.json │ │ ├── keystoneAuthResponse.json │ │ ├── keystoneAuthResponse_openstack.json │ │ ├── logback.xml │ │ ├── raxAuth.json │ │ ├── raxCryptoAuth.json │ │ ├── raxVersion.json │ │ ├── role_create_response.json │ │ ├── role_list_response.json │ │ ├── service_create_response.json │ │ ├── service_list_response.json │ │ ├── tenant_create_response.json │ │ ├── tenant_details.json │ │ ├── tenant_list.json │ │ ├── tenant_list_att.json │ │ ├── tenant_update_response.json │ │ ├── token_details.json │ │ ├── user_create_response.json │ │ ├── user_details.json │ │ ├── user_endpoints.json │ │ ├── user_list.json │ │ ├── user_role_list.json │ │ ├── user_tenant_role_list.json │ │ ├── user_update_response.json │ │ └── v3/ │ │ ├── auth-accesskey.json │ │ ├── auth-password-project-scoped-id-domain-id.json │ │ ├── auth-password-project-scoped-id-domain-name.json │ │ ├── auth-password-project-scoped-name-domain-backwards-compat.json │ │ ├── auth-password-project-scoped-name-domain-id.json │ │ ├── auth-password-project-scoped-name-domain-name.json │ │ ├── auth-password-scoped.json │ │ ├── auth-password.json │ │ ├── auth-token-scoped.json │ │ ├── auth-token.json │ │ ├── endpoints.json │ │ ├── groups.json │ │ ├── project.json │ │ ├── projects.json │ │ ├── region.json │ │ ├── regions.json │ │ ├── token.json │ │ ├── user.json │ │ └── users.json │ ├── openstack-neutron/ │ │ ├── README.md │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── openstack/ │ │ │ └── neutron/ │ │ │ └── v2/ │ │ │ ├── NeutronApi.java │ │ │ ├── NeutronApiMetadata.java │ │ │ ├── config/ │ │ │ │ └── NeutronHttpApiModule.java │ │ │ ├── domain/ │ │ │ │ ├── AddressPair.java │ │ │ │ ├── AllocationPool.java │ │ │ │ ├── CreateFirewall.java │ │ │ │ ├── CreateFirewallPolicy.java │ │ │ │ ├── CreateFirewallRule.java │ │ │ │ ├── ExternalGatewayInfo.java │ │ │ │ ├── ExtraDhcpOption.java │ │ │ │ ├── Firewall.java │ │ │ │ ├── FirewallPolicies.java │ │ │ │ ├── FirewallPolicy.java │ │ │ │ ├── FirewallRule.java │ │ │ │ ├── FirewallRules.java │ │ │ │ ├── Firewalls.java │ │ │ │ ├── FloatingIP.java │ │ │ │ ├── FloatingIPs.java │ │ │ │ ├── HostRoute.java │ │ │ │ ├── IP.java │ │ │ │ ├── IPv6DHCPMode.java │ │ │ │ ├── IpVersion.java │ │ │ │ ├── Network.java │ │ │ │ ├── NetworkSegment.java │ │ │ │ ├── NetworkStatus.java │ │ │ │ ├── NetworkType.java │ │ │ │ ├── Networks.java │ │ │ │ ├── Port.java │ │ │ │ ├── Ports.java │ │ │ │ ├── Router.java │ │ │ │ ├── RouterInterface.java │ │ │ │ ├── Routers.java │ │ │ │ ├── Rule.java │ │ │ │ ├── RuleDirection.java │ │ │ │ ├── RuleEthertype.java │ │ │ │ ├── RuleProtocol.java │ │ │ │ ├── Rules.java │ │ │ │ ├── SecurityGroup.java │ │ │ │ ├── SecurityGroups.java │ │ │ │ ├── Subnet.java │ │ │ │ ├── Subnets.java │ │ │ │ ├── UpdateFirewall.java │ │ │ │ ├── UpdateFirewallPolicy.java │ │ │ │ ├── UpdateFirewallRule.java │ │ │ │ ├── VIFType.java │ │ │ │ ├── VNICType.java │ │ │ │ └── lbaas/ │ │ │ │ └── v1/ │ │ │ │ ├── HealthMonitor.java │ │ │ │ ├── HealthMonitorStatus.java │ │ │ │ ├── HealthMonitors.java │ │ │ │ ├── HttpMethod.java │ │ │ │ ├── LBaaSStatus.java │ │ │ │ ├── Member.java │ │ │ │ ├── Members.java │ │ │ │ ├── Pool.java │ │ │ │ ├── PoolStatus.java │ │ │ │ ├── Pools.java │ │ │ │ ├── ProbeType.java │ │ │ │ ├── Protocol.java │ │ │ │ ├── SessionPersistence.java │ │ │ │ ├── VIP.java │ │ │ │ └── VIPs.java │ │ │ ├── extensions/ │ │ │ │ ├── ExtensionNamespaces.java │ │ │ │ ├── FWaaSApi.java │ │ │ │ ├── RouterApi.java │ │ │ │ └── lbaas/ │ │ │ │ └── v1/ │ │ │ │ └── LBaaSApi.java │ │ │ ├── fallbacks/ │ │ │ │ ├── EmptyFloatingIPsFallback.java │ │ │ │ ├── EmptyNetworksFallback.java │ │ │ │ ├── EmptyPortsFallback.java │ │ │ │ ├── EmptyRoutersFallback.java │ │ │ │ ├── EmptyRulesFallback.java │ │ │ │ ├── EmptySecurityGroupsFallback.java │ │ │ │ ├── EmptySubnetsFallback.java │ │ │ │ └── lbaas/ │ │ │ │ └── v1/ │ │ │ │ ├── EmptyHealthMonitorsFallback.java │ │ │ │ ├── EmptyMembersFallback.java │ │ │ │ ├── EmptyPoolsFallback.java │ │ │ │ └── EmptyVIPsFallback.java │ │ │ ├── features/ │ │ │ │ ├── FloatingIPApi.java │ │ │ │ ├── NetworkApi.java │ │ │ │ ├── PortApi.java │ │ │ │ ├── SecurityGroupApi.java │ │ │ │ └── SubnetApi.java │ │ │ ├── functions/ │ │ │ │ ├── FirewallPolicyToPagedIterable.java │ │ │ │ ├── FirewallRuleToPagedIterable.java │ │ │ │ ├── FirewallToPagedIterable.java │ │ │ │ ├── FloatingIPsToPagedIterable.java │ │ │ │ ├── NetworksToPagedIterable.java │ │ │ │ ├── ParseFirewallPolicies.java │ │ │ │ ├── ParseFirewallRules.java │ │ │ │ ├── ParseFirewalls.java │ │ │ │ ├── ParseFloatingIPs.java │ │ │ │ ├── ParseNetworks.java │ │ │ │ ├── ParsePorts.java │ │ │ │ ├── ParseRouters.java │ │ │ │ ├── ParseRules.java │ │ │ │ ├── ParseSecurityGroups.java │ │ │ │ ├── ParseSubnets.java │ │ │ │ ├── PortsToPagedIterable.java │ │ │ │ ├── RouterToPagedIterable.java │ │ │ │ ├── RulesToPagedIterable.java │ │ │ │ ├── SecurityGroupsToPagedIterable.java │ │ │ │ ├── SubnetsToPagedIterable.java │ │ │ │ ├── VersionAwareRegionToEndpoint.java │ │ │ │ └── lbaas/ │ │ │ │ └── v1/ │ │ │ │ ├── HealthMonitorsToPagedIterable.java │ │ │ │ ├── MembersToPagedIterable.java │ │ │ │ ├── ParseHealthMonitors.java │ │ │ │ ├── ParseMembers.java │ │ │ │ ├── ParsePools.java │ │ │ │ ├── ParseVIPs.java │ │ │ │ ├── PoolsToPagedIterable.java │ │ │ │ └── VIPsToPagedIterable.java │ │ │ ├── handlers/ │ │ │ │ └── NeutronErrorHandler.java │ │ │ └── options/ │ │ │ └── EmptyOptions.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── openstack/ │ │ │ └── neutron/ │ │ │ └── v2/ │ │ │ ├── NeutronApiMetadataTest.java │ │ │ ├── extensions/ │ │ │ │ ├── FWaaSApiLiveTest.java │ │ │ │ ├── FWaaSApiMockTest.java │ │ │ │ ├── RouterApiLiveTest.java │ │ │ │ ├── RouterApiMockTest.java │ │ │ │ └── lbaas/ │ │ │ │ └── v1/ │ │ │ │ ├── LBaaSApiLiveTest.java │ │ │ │ └── LBaaSApiMockTest.java │ │ │ ├── features/ │ │ │ │ ├── ExtensionApiLiveTest.java │ │ │ │ ├── ExtensionApiMockTest.java │ │ │ │ ├── FloatingIPApiLiveTest.java │ │ │ │ ├── FloatingIPApiMockTest.java │ │ │ │ ├── NetworkApiLiveTest.java │ │ │ │ ├── NetworkApiMockTest.java │ │ │ │ ├── PortApiLiveTest.java │ │ │ │ ├── PortApiMockTest.java │ │ │ │ ├── SecurityGroupApiLiveTest.java │ │ │ │ ├── SecurityGroupApiMockTest.java │ │ │ │ ├── SubnetApiLiveTest.java │ │ │ │ └── SubnetApiMockTest.java │ │ │ ├── internal/ │ │ │ │ ├── BaseNeutronApiLiveTest.java │ │ │ │ └── BaseNeutronApiMockTest.java │ │ │ └── util/ │ │ │ ├── ClassUtil.java │ │ │ └── PredicateUtil.java │ │ └── resources/ │ │ ├── access.json │ │ ├── extension_details.json │ │ ├── extension_list.json │ │ ├── extension_list_with_lbaas_v1_response.json │ │ ├── extension_list_without_lbaas_v1_response.json │ │ ├── firewall_create_request.json │ │ ├── firewall_create_response.json │ │ ├── firewall_get_response.json │ │ ├── firewall_list_response.json │ │ ├── firewall_policy_create_request.json │ │ ├── firewall_policy_create_response.json │ │ ├── firewall_policy_get_response.json │ │ ├── firewall_policy_insert_rule_request.json │ │ ├── firewall_policy_insert_rule_response.json │ │ ├── firewall_policy_list_response.json │ │ ├── firewall_rule_create_request.json │ │ ├── firewall_rule_create_response.json │ │ ├── firewall_rule_get_response.json │ │ ├── firewall_rule_update_request.json │ │ ├── firewall_rule_update_response.json │ │ ├── firewall_update_request.json │ │ ├── firewall_update_response.json │ │ ├── floatingip_create_request.json │ │ ├── floatingip_create_response.json │ │ ├── floatingip_get_response.json │ │ ├── floatingip_list_response.json │ │ ├── floatingip_list_response_paged1.json │ │ ├── floatingip_list_response_paged2.json │ │ ├── floatingip_update_dissociate_request.json │ │ ├── floatingip_update_dissociate_response.json │ │ ├── floatingip_update_request.json │ │ ├── floatingip_update_response.json │ │ ├── lbaas/ │ │ │ └── v1/ │ │ │ ├── health_monitor_create_request.json │ │ │ ├── health_monitor_create_response.json │ │ │ ├── health_monitor_get_response.json │ │ │ ├── health_monitor_list_response_paged1.json │ │ │ ├── health_monitor_list_response_paged2.json │ │ │ ├── health_monitor_update_request.json │ │ │ ├── health_monitor_update_response.json │ │ │ ├── member_create_request.json │ │ │ ├── member_create_response.json │ │ │ ├── member_get_response.json │ │ │ ├── member_list_response_paged1.json │ │ │ ├── member_list_response_paged2.json │ │ │ ├── member_update_request.json │ │ │ ├── member_update_response.json │ │ │ ├── pool_associate_health_monitor_request.json │ │ │ ├── pool_associate_health_monitor_response.json │ │ │ ├── pool_create_request.json │ │ │ ├── pool_create_response.json │ │ │ ├── pool_get_response.json │ │ │ ├── pool_list_response_paged1.json │ │ │ ├── pool_list_response_paged2.json │ │ │ ├── pool_update_request.json │ │ │ ├── pool_update_response.json │ │ │ ├── vip_create_request.json │ │ │ ├── vip_create_response.json │ │ │ ├── vip_get_response.json │ │ │ ├── vip_list_response_paged1.json │ │ │ ├── vip_list_response_paged2.json │ │ │ ├── vip_update_request.json │ │ │ └── vip_update_response.json │ │ ├── list_networks.json │ │ ├── list_ports.json │ │ ├── list_routers.json │ │ ├── list_subnets.json │ │ ├── logback.xml │ │ ├── network.json │ │ ├── network_bulk_create_request.json │ │ ├── network_bulk_create_response.json │ │ ├── network_create_request.json │ │ ├── network_create_response.json │ │ ├── network_get_response.json │ │ ├── network_list_response.json │ │ ├── network_list_response_paged1.json │ │ ├── network_list_response_paged2.json │ │ ├── network_update_request.json │ │ ├── network_update_response.json │ │ ├── port.json │ │ ├── port_create_bulk_request.json │ │ ├── port_create_bulk_response.json │ │ ├── port_create_request.json │ │ ├── port_create_response.json │ │ ├── port_get_response.json │ │ ├── port_list_response.json │ │ ├── port_list_response_paged1.json │ │ ├── port_list_response_paged2.json │ │ ├── port_update_request.json │ │ ├── port_update_response.json │ │ ├── router.json │ │ ├── router_add_interface_port_request.json │ │ ├── router_add_interface_request.json │ │ ├── router_add_interface_response.json │ │ ├── router_create_request.json │ │ ├── router_create_response.json │ │ ├── router_get_response.json │ │ ├── router_list_response.json │ │ ├── router_list_response_paged1.json │ │ ├── router_list_response_paged2.json │ │ ├── router_remove_interface_port_request.json │ │ ├── router_remove_interface_subnet_request.json │ │ ├── router_update_request.json │ │ ├── router_update_response.json │ │ ├── security_group_create_request.json │ │ ├── security_group_create_response.json │ │ ├── security_group_get_response.json │ │ ├── security_group_list_response.json │ │ ├── security_group_list_response_paged1.json │ │ ├── security_group_list_response_paged2.json │ │ ├── security_group_rule_create_request.json │ │ ├── security_group_rule_create_response.json │ │ ├── security_group_rule_get_response.json │ │ ├── security_group_rule_list_response.json │ │ ├── security_group_rule_list_response_paged1.json │ │ ├── security_group_rule_list_response_paged2.json │ │ ├── subnet.json │ │ ├── subnet_bulk_create_request.json │ │ ├── subnet_bulk_create_response.json │ │ ├── subnet_create_request.json │ │ ├── subnet_create_response.json │ │ ├── subnet_get_response.json │ │ ├── subnet_list_response.json │ │ ├── subnet_list_response_pages1.json │ │ ├── subnet_list_response_pages2.json │ │ ├── subnet_update_request.json │ │ └── subnet_update_response.json │ ├── openstack-nova/ │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── openstack/ │ │ │ └── nova/ │ │ │ └── v2_0/ │ │ │ ├── NovaApi.java │ │ │ ├── NovaApiMetadata.java │ │ │ ├── binders/ │ │ │ │ ├── BindConsoleToJsonPayload.java │ │ │ │ ├── BindKeyPairToJsonPayload.java │ │ │ │ ├── BindMetadataToJsonPayload.java │ │ │ │ └── BindSecurityGroupRuleToJsonPayload.java │ │ │ ├── compute/ │ │ │ │ ├── NovaComputeService.java │ │ │ │ ├── NovaComputeServiceAdapter.java │ │ │ │ ├── config/ │ │ │ │ │ └── NovaComputeServiceContextModule.java │ │ │ │ ├── extensions/ │ │ │ │ │ ├── NeutronSecurityGroupExtension.java │ │ │ │ │ ├── NovaImageExtension.java │ │ │ │ │ └── NovaSecurityGroupExtension.java │ │ │ │ ├── functions/ │ │ │ │ │ ├── AllocateAndAddFloatingIpToNode.java │ │ │ │ │ ├── CleanupResources.java │ │ │ │ │ ├── CreateSecurityGroupIfNeeded.java │ │ │ │ │ ├── FlavorInRegionToHardware.java │ │ │ │ │ ├── ImageInRegionToImage.java │ │ │ │ │ ├── ImageToOperatingSystem.java │ │ │ │ │ ├── NeutronSecurityGroupToSecurityGroup.java │ │ │ │ │ ├── NovaSecurityGroupInRegionToSecurityGroup.java │ │ │ │ │ ├── NovaSecurityGroupToSecurityGroup.java │ │ │ │ │ ├── OrphanedGroupsByRegionId.java │ │ │ │ │ ├── RemoveFloatingIpFromNodeAndDeallocate.java │ │ │ │ │ └── ServerInRegionToNodeMetadata.java │ │ │ │ ├── loaders/ │ │ │ │ │ ├── FindSecurityGroupOrCreate.java │ │ │ │ │ └── LoadFloatingIpsForInstance.java │ │ │ │ ├── options/ │ │ │ │ │ ├── NodeAndNovaTemplateOptions.java │ │ │ │ │ └── NovaTemplateOptions.java │ │ │ │ ├── predicates/ │ │ │ │ │ └── AllNodesInGroupTerminated.java │ │ │ │ └── strategy/ │ │ │ │ └── ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddToSet.java │ │ │ ├── config/ │ │ │ │ ├── NovaHttpApiModule.java │ │ │ │ ├── NovaParserModule.java │ │ │ │ └── NovaProperties.java │ │ │ ├── domain/ │ │ │ │ ├── Address.java │ │ │ │ ├── BackupType.java │ │ │ │ ├── BlockDeviceMapping.java │ │ │ │ ├── Console.java │ │ │ │ ├── FixedIP.java │ │ │ │ ├── Flavor.java │ │ │ │ ├── FloatingIP.java │ │ │ │ ├── FloatingIPPool.java │ │ │ │ ├── FloatingIpForServer.java │ │ │ │ ├── Host.java │ │ │ │ ├── HostAggregate.java │ │ │ │ ├── HostResourceUsage.java │ │ │ │ ├── Image.java │ │ │ │ ├── Ingress.java │ │ │ │ ├── InterfaceAttachment.java │ │ │ │ ├── KeyPair.java │ │ │ │ ├── Network.java │ │ │ │ ├── PortInterface.java │ │ │ │ ├── PortState.java │ │ │ │ ├── Quota.java │ │ │ │ ├── RebootType.java │ │ │ │ ├── SecurityGroup.java │ │ │ │ ├── SecurityGroupRule.java │ │ │ │ ├── Server.java │ │ │ │ ├── ServerCreated.java │ │ │ │ ├── ServerExtendedAttributes.java │ │ │ │ ├── ServerExtendedStatus.java │ │ │ │ ├── ServerWithSecurityGroups.java │ │ │ │ ├── SimpleServerUsage.java │ │ │ │ ├── SimpleTenantUsage.java │ │ │ │ ├── TenantIdAndName.java │ │ │ │ ├── VirtualInterface.java │ │ │ │ ├── Volume.java │ │ │ │ ├── VolumeAttachment.java │ │ │ │ ├── VolumeSnapshot.java │ │ │ │ ├── VolumeType.java │ │ │ │ ├── regionscoped/ │ │ │ │ │ ├── AvailabilityZone.java │ │ │ │ │ ├── AvailabilityZoneDetails.java │ │ │ │ │ ├── FlavorInRegion.java │ │ │ │ │ ├── Hypervisor.java │ │ │ │ │ ├── HypervisorDetails.java │ │ │ │ │ ├── ImageInRegion.java │ │ │ │ │ ├── NeutronSecurityGroupInRegion.java │ │ │ │ │ ├── RegionAndId.java │ │ │ │ │ ├── RegionAndName.java │ │ │ │ │ ├── RegionSecurityGroupNameAndPorts.java │ │ │ │ │ ├── SecurityGroupInRegion.java │ │ │ │ │ ├── ServerInRegion.java │ │ │ │ │ └── ZoneState.java │ │ │ │ └── zonescoped/ │ │ │ │ ├── AvailabilityZone.java │ │ │ │ ├── FlavorInRegion.java │ │ │ │ ├── ImageInRegion.java │ │ │ │ ├── RegionAndId.java │ │ │ │ ├── RegionAndName.java │ │ │ │ ├── RegionSecurityGroupNameAndPorts.java │ │ │ │ ├── SecurityGroupInRegion.java │ │ │ │ ├── ServerInRegion.java │ │ │ │ └── ZoneState.java │ │ │ ├── extensions/ │ │ │ │ ├── AttachInterfaceApi.java │ │ │ │ ├── AvailabilityZoneApi.java │ │ │ │ ├── ConsolesApi.java │ │ │ │ ├── ExtensionAliases.java │ │ │ │ ├── ExtensionNames.java │ │ │ │ ├── ExtensionNamespaces.java │ │ │ │ ├── FlavorExtraSpecsApi.java │ │ │ │ ├── FloatingIPApi.java │ │ │ │ ├── FloatingIPPoolApi.java │ │ │ │ ├── HostAdministrationApi.java │ │ │ │ ├── HostAggregateApi.java │ │ │ │ ├── HypervisorApi.java │ │ │ │ ├── KeyPairApi.java │ │ │ │ ├── QuotaApi.java │ │ │ │ ├── SecurityGroupApi.java │ │ │ │ ├── ServerAdminApi.java │ │ │ │ ├── ServerWithSecurityGroupsApi.java │ │ │ │ ├── SimpleTenantUsageApi.java │ │ │ │ ├── VirtualInterfaceApi.java │ │ │ │ ├── VolumeApi.java │ │ │ │ ├── VolumeAttachmentApi.java │ │ │ │ └── VolumeTypeApi.java │ │ │ ├── features/ │ │ │ │ ├── FlavorApi.java │ │ │ │ ├── ImageApi.java │ │ │ │ └── ServerApi.java │ │ │ ├── functions/ │ │ │ │ ├── FieldValueResponseParsers.java │ │ │ │ ├── OverLimitParser.java │ │ │ │ ├── ParseImageIdFromLocationHeader.java │ │ │ │ └── internal/ │ │ │ │ ├── OnlyMetadataValueOrNull.java │ │ │ │ ├── ParseDiagnostics.java │ │ │ │ ├── ParseFlavorDetails.java │ │ │ │ ├── ParseFlavors.java │ │ │ │ ├── ParseImageDetails.java │ │ │ │ ├── ParseImages.java │ │ │ │ ├── ParseKeyPairs.java │ │ │ │ ├── ParseServerDetails.java │ │ │ │ └── ParseServers.java │ │ │ ├── handlers/ │ │ │ │ └── NovaErrorHandler.java │ │ │ ├── options/ │ │ │ │ ├── CreateBackupOfServerOptions.java │ │ │ │ ├── CreateServerOptions.java │ │ │ │ ├── CreateVolumeOptions.java │ │ │ │ ├── CreateVolumeSnapshotOptions.java │ │ │ │ ├── CreateVolumeTypeOptions.java │ │ │ │ ├── ListOptions.java │ │ │ │ └── RebuildServerOptions.java │ │ │ └── predicates/ │ │ │ ├── FindSecurityGroupWithNameAndReturnTrue.java │ │ │ ├── ImagePredicates.java │ │ │ ├── KeyPairPredicates.java │ │ │ └── SecurityGroupPredicates.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── openstack/ │ │ │ └── nova/ │ │ │ └── v2_0/ │ │ │ ├── AccessKeyAndSecretKeyAndTenantIdAuthenticationExpectTest.java │ │ │ ├── AccessKeyAndSecretKeyAndTenantNamePropertyAuthenticationExpectTest.java │ │ │ ├── AccessKeyAndSecretKeyAuthenticationExpectTest.java │ │ │ ├── EndpointIdIsRandomExpectTest.java │ │ │ ├── NovaApiMetadataTest.java │ │ │ ├── PasswordAuthenticationExpectTest.java │ │ │ ├── PasswordAuthenticationWithTenantNameExpectTest.java │ │ │ ├── compute/ │ │ │ │ ├── NovaComputeServiceAdapterExpectTest.java │ │ │ │ ├── NovaComputeServiceExpectTest.java │ │ │ │ ├── NovaComputeServiceLiveTest.java │ │ │ │ ├── NovaWithNeutronComputeServiceLiveTest.java │ │ │ │ ├── extensions/ │ │ │ │ │ ├── NeutronSecurityGroupExtensionLiveTest.java │ │ │ │ │ ├── NovaImageExtensionExpectTest.java │ │ │ │ │ ├── NovaImageExtensionLiveTest.java │ │ │ │ │ ├── NovaSecurityGroupExtensionExpectTest.java │ │ │ │ │ └── NovaSecurityGroupExtensionLiveTest.java │ │ │ │ ├── functions/ │ │ │ │ │ ├── AllocateAndAddFloatingIpToNodeExpectTest.java │ │ │ │ │ ├── FlavorInRegionToHardwareTest.java │ │ │ │ │ ├── ImageInRegionToImageTest.java │ │ │ │ │ ├── ImageToOperatingSystemTest.java │ │ │ │ │ ├── NovaSecurityGroupInRegionToSecurityGroupTest.java │ │ │ │ │ ├── OrphanedGroupsByRegionIdTest.java │ │ │ │ │ └── ServerInRegionToNodeMetadataTest.java │ │ │ │ ├── loaders/ │ │ │ │ │ ├── FindSecurityGroupInRegionOrCreateTest.java │ │ │ │ │ └── LoadFloatingIpsForInstanceTest.java │ │ │ │ └── options/ │ │ │ │ └── NovaTemplateOptionsTest.java │ │ │ ├── config/ │ │ │ │ └── ImageAdapterTest.java │ │ │ ├── extensions/ │ │ │ │ ├── AdminActionsApiExpectTest.java │ │ │ │ ├── AdminActionsApiLiveTest.java │ │ │ │ ├── AttachInterfaceApiExpectTest.java │ │ │ │ ├── AvailabilityZoneApiExpectTest.java │ │ │ │ ├── AvailabilityZonesApiLiveTest.java │ │ │ │ ├── ConsolesApiLiveTest.java │ │ │ │ ├── ConsolesApiMockTest.java │ │ │ │ ├── DeprecatedAvailabilityZoneApiExpectTest.java │ │ │ │ ├── DeprecatedAvailabilityZonesApiLiveTest.java │ │ │ │ ├── ExtendedAvailabilityZoneExpectTest.java │ │ │ │ ├── ExtendedAvailabilityZoneLiveTest.java │ │ │ │ ├── FlavorExtraSpecsApiExpectTest.java │ │ │ │ ├── FlavorExtraSpecsApiLiveTest.java │ │ │ │ ├── FloatingIPApiExpectTest.java │ │ │ │ ├── FloatingIPApiLiveTest.java │ │ │ │ ├── FloatingIPPoolApiExpectTest.java │ │ │ │ ├── FloatingIPPoolApiLiveTest.java │ │ │ │ ├── HostAdministrationApiExpectTest.java │ │ │ │ ├── HostAdministrationApiLiveTest.java │ │ │ │ ├── HostAggregateApiExpectTest.java │ │ │ │ ├── HostAggregateApiLiveTest.java │ │ │ │ ├── HypervisorApiLiveTest.java │ │ │ │ ├── HypervisorApiMockTest.java │ │ │ │ ├── KeyPairApiExpectTest.java │ │ │ │ ├── KeyPairApiLiveTest.java │ │ │ │ ├── QuotaApiExpectTest.java │ │ │ │ ├── QuotaApiLiveTest.java │ │ │ │ ├── SecurityGroupApiExpectTest.java │ │ │ │ ├── SecurityGroupApiLiveTest.java │ │ │ │ ├── ServerWithSecurityGroupsApiExpectTest.java │ │ │ │ ├── ServerWithSecurityGroupsApiLiveTest.java │ │ │ │ ├── SimpleTenantUsageApiExpectTest.java │ │ │ │ ├── SimpleTenantUsageApiLiveTest.java │ │ │ │ ├── VirtualInterfaceApiExpectTest.java │ │ │ │ ├── VirtualInterfaceApiLiveTest.java │ │ │ │ ├── VolumeApiExpectTest.java │ │ │ │ ├── VolumeApiLiveTest.java │ │ │ │ ├── VolumeAttachmentApiExpectTest.java │ │ │ │ ├── VolumeAttachmentApiLiveTest.java │ │ │ │ ├── VolumeTypeApiExpectTest.java │ │ │ │ └── VolumeTypeApiLiveTest.java │ │ │ ├── features/ │ │ │ │ ├── ExtensionApiExpectTest.java │ │ │ │ ├── ExtensionApiLiveTest.java │ │ │ │ ├── FlavorApiExpectTest.java │ │ │ │ ├── FlavorApiLiveTest.java │ │ │ │ ├── ImageApiExpectTest.java │ │ │ │ ├── ImageApiLiveTest.java │ │ │ │ ├── ImageApiMockTest.java │ │ │ │ ├── ServerApiExpectTest.java │ │ │ │ └── ServerApiLiveTest.java │ │ │ ├── functions/ │ │ │ │ ├── CreateSecurityGroupIfNeededTest.java │ │ │ │ ├── FindSecurityGroupWithNameAndReturnTrueExpectTest.java │ │ │ │ └── InternalURLLiveTest.java │ │ │ ├── handlers/ │ │ │ │ └── NovaErrorHandlerTest.java │ │ │ ├── internal/ │ │ │ │ ├── BaseNovaApiExpectTest.java │ │ │ │ ├── BaseNovaApiLiveTest.java │ │ │ │ ├── BaseNovaComputeServiceContextExpectTest.java │ │ │ │ ├── BaseNovaComputeServiceExpectTest.java │ │ │ │ └── BaseNovaExpectTest.java │ │ │ ├── options/ │ │ │ │ ├── CreateServerOptionsTest.java │ │ │ │ └── ListOptionsTest.java │ │ │ ├── parse/ │ │ │ │ ├── ParseComputeServiceTypicalSecurityGroupTest.java │ │ │ │ ├── ParseCreateFlavorTest.java │ │ │ │ ├── ParseCreatedServerTest.java │ │ │ │ ├── ParseExtensionListNormalTest.java │ │ │ │ ├── ParseExtensionListTest.java │ │ │ │ ├── ParseExtensionTest.java │ │ │ │ ├── ParseFlavorListTest.java │ │ │ │ ├── ParseFlavorTest.java │ │ │ │ ├── ParseFloatingIPListTest.java │ │ │ │ ├── ParseFloatingIPPoolListTest.java │ │ │ │ ├── ParseFloatingIPTest.java │ │ │ │ ├── ParseImageListTest.java │ │ │ │ ├── ParseImageTest.java │ │ │ │ ├── ParseKeyPairListTest.java │ │ │ │ ├── ParseKeyPairTest.java │ │ │ │ ├── ParseMetadataItemTest.java │ │ │ │ ├── ParseMetadataListTest.java │ │ │ │ ├── ParseMetadataUpdateTest.java │ │ │ │ ├── ParseNOVNCConsoleTest.java │ │ │ │ ├── ParseRDPConsoleTest.java │ │ │ │ ├── ParseSPICEConsoleTest.java │ │ │ │ ├── ParseSecurityGroupListTest.java │ │ │ │ ├── ParseSecurityGroupTest.java │ │ │ │ ├── ParseServerDetailsEssexTest.java │ │ │ │ ├── ParseServerDetailsStatesTest.java │ │ │ │ ├── ParseServerDiagnostics.java │ │ │ │ ├── ParseServerListTest.java │ │ │ │ ├── ParseServerTest.java │ │ │ │ ├── ParseServerWithAddressExtensionsTest.java │ │ │ │ ├── ParseServerWithAllExtensionsTest.java │ │ │ │ ├── ParseServerWithInternetAddressesTest.java │ │ │ │ ├── ParseServerWithoutImageTest.java │ │ │ │ ├── ParseXVPVNCConsoleTest.java │ │ │ │ └── PublicIpsInPrivateAddressBlockExpectTest.java │ │ │ └── predicates/ │ │ │ ├── ImagePredicatesTest.java │ │ │ └── SecurityGroupPredicatesTest.java │ │ └── resources/ │ │ ├── access.json │ │ ├── attach_interface_details.json │ │ ├── attach_interfaces_list.json │ │ ├── attachment_details.json │ │ ├── attachment_list.json │ │ ├── availability_zone_list.json │ │ ├── extension_details.json │ │ ├── extension_list.json │ │ ├── extension_list_full.json │ │ ├── extension_list_full_no_namespaces.json │ │ ├── extension_list_normal.json │ │ ├── extension_list_openstack.json │ │ ├── flavor_details.json │ │ ├── flavor_list.json │ │ ├── flavor_list_detail.json │ │ ├── flavor_list_detail_openstack.json │ │ ├── flavor_new.json │ │ ├── floatingip_details.json │ │ ├── floatingip_list.json │ │ ├── floatingippool_list.json │ │ ├── host.json │ │ ├── host_aggregate_details.json │ │ ├── host_aggregate_list.json │ │ ├── host_aggregate_with_host_details.json │ │ ├── hosts_list.json │ │ ├── hypervisor_details.json │ │ ├── hypervisor_list.json │ │ ├── image_active.json │ │ ├── image_details.json │ │ ├── image_details_with_block_device_mapping.json │ │ ├── image_details_without_metadata.json │ │ ├── image_list.json │ │ ├── image_list_detail.json │ │ ├── image_list_detail_imageextension.json │ │ ├── image_list_detail_openstack.json │ │ ├── image_list_with_block_device_mapping.json │ │ ├── keypair_created_computeservice.json │ │ ├── keypair_details.json │ │ ├── keypair_list.json │ │ ├── listAvailabilityZones.json │ │ ├── logback-test.xml │ │ ├── metadata_item.json │ │ ├── metadata_list.json │ │ ├── metadata_updated.json │ │ ├── new_server.json │ │ ├── new_server_config_drive.json │ │ ├── new_server_disk_config_auto.json │ │ ├── new_server_disk_config_manual.json │ │ ├── new_server_in_zone.json │ │ ├── new_server_networks_response.json │ │ ├── new_server_no_adminpass.json │ │ ├── new_server_nova_networks.json │ │ ├── novnc_console.json │ │ ├── quotas.json │ │ ├── rdp_console.json │ │ ├── securitygroup_created.json │ │ ├── securitygroup_details.json │ │ ├── securitygroup_details_computeservice_typical.json │ │ ├── securitygroup_details_extension.json │ │ ├── securitygroup_details_extension_norules.json │ │ ├── securitygroup_details_port22.json │ │ ├── securitygroup_list.json │ │ ├── securitygroup_list_details_computeservice_typical.json │ │ ├── securitygroup_list_extension.json │ │ ├── securitygrouprule_created.json │ │ ├── securitygrouprule_created_cidr.json │ │ ├── securitygrouprule_created_group.json │ │ ├── server_details.json │ │ ├── server_details_devstack.json │ │ ├── server_details_openstack.json │ │ ├── server_details_suspended.json │ │ ├── server_details_with_address_ext.json │ │ ├── server_details_without_image.json │ │ ├── server_diagnostics.json │ │ ├── server_list.json │ │ ├── server_list_details.json │ │ ├── server_list_details_essex.json │ │ ├── server_list_details_states.json │ │ ├── server_public_ip_in_private.json │ │ ├── server_with_security_groups.json │ │ ├── server_with_security_groups_extension.json │ │ ├── simple_tenant_usage.json │ │ ├── simple_tenant_usages.json │ │ ├── snapshot_details.json │ │ ├── snapshot_list.json │ │ ├── snapshot_list_detail.json │ │ ├── spice_console.json │ │ ├── virtual_interfaces_list.json │ │ ├── volume_details.json │ │ ├── volume_list.json │ │ ├── volume_list_detail.json │ │ ├── volume_type.json │ │ ├── volume_type_extra_specs.json │ │ ├── volume_type_list.json │ │ └── xvpvnc_console.json │ ├── openstack-nova-ec2/ │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── openstack/ │ │ │ └── nova/ │ │ │ └── ec2/ │ │ │ ├── NovaEC2Api.java │ │ │ ├── NovaEC2ApiMetadata.java │ │ │ ├── config/ │ │ │ │ ├── HyphenToNullIso8601Module.java │ │ │ │ ├── NovaEC2ComputeServiceContextModule.java │ │ │ │ └── NovaEC2HttpApiModule.java │ │ │ ├── features/ │ │ │ │ └── NovaEC2KeyPairApi.java │ │ │ ├── internal/ │ │ │ │ └── HyphenToNullIso8601Codec.java │ │ │ ├── loaders/ │ │ │ │ └── NovaCreateSecurityGroupIfNeeded.java │ │ │ ├── strategy/ │ │ │ │ └── NovaReviseParsedImage.java │ │ │ └── xml/ │ │ │ ├── NovaCreateVolumeResponseHandler.java │ │ │ └── NovaDescribeImagesResponseHandler.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── openstack/ │ │ │ └── nova/ │ │ │ └── ec2/ │ │ │ ├── NovaEC2ApiMetadataTest.java │ │ │ ├── NovaEC2ContextBuilderTest.java │ │ │ ├── compute/ │ │ │ │ └── NovaEC2ComputeServiceLiveTest.java │ │ │ ├── features/ │ │ │ │ ├── NovaEC2AMIApiExpectTest.java │ │ │ │ ├── NovaEC2AMIApiLiveTest.java │ │ │ │ ├── NovaEC2AvailabilityZoneAndRegionApiLiveTest.java │ │ │ │ ├── NovaEC2ElasticBlockStoreApiLiveTest.java │ │ │ │ ├── NovaEC2ElasticBlockStoreExpectApiTest.java │ │ │ │ ├── NovaEC2ElasticIPAddressApiLiveTest.java │ │ │ │ ├── NovaEC2InstanceApiExpectTest.java │ │ │ │ ├── NovaEC2InstanceApiLiveTest.java │ │ │ │ ├── NovaEC2KeyPairApiExpectTest.java │ │ │ │ ├── NovaEC2KeyPairApiLiveTest.java │ │ │ │ ├── NovaEC2SecurityGroupApiLiveTest.java │ │ │ │ └── NovaSubnetApiLiveTest.java │ │ │ ├── internal/ │ │ │ │ └── BaseNovaEC2RestApiExpectTest.java │ │ │ └── strategy/ │ │ │ └── NovaReviseParsedImageTest.java │ │ └── resources/ │ │ ├── nova_ec2_availabilityZones.xml │ │ ├── nova_ec2_describe_instances.xml │ │ ├── nova_ec2_describe_volumes.xml │ │ ├── nova_ec2_images.xml │ │ ├── nova_ec2_images_with_ramdisk.xml │ │ └── nova_ec2_import_keypair_response.xml │ ├── openstack-swift/ │ │ ├── README.md │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── openstack/ │ │ │ └── swift/ │ │ │ └── v1/ │ │ │ ├── SwiftApi.java │ │ │ ├── SwiftApiMetadata.java │ │ │ ├── SwiftFallbacks.java │ │ │ ├── TemporaryUrlSigner.java │ │ │ ├── binders/ │ │ │ │ ├── BindMetadataToHeaders.java │ │ │ │ ├── BindToHeaders.java │ │ │ │ ├── SetPayload.java │ │ │ │ └── TempAuthBinder.java │ │ │ ├── blobstore/ │ │ │ │ ├── RegionScopedBlobStoreContext.java │ │ │ │ ├── RegionScopedSwiftBlobStore.java │ │ │ │ ├── RegionScopedTemporaryUrlBlobSigner.java │ │ │ │ ├── config/ │ │ │ │ │ ├── SignUsingTemporaryUrls.java │ │ │ │ │ └── SwiftBlobStoreContextModule.java │ │ │ │ └── functions/ │ │ │ │ ├── ToBlobMetadata.java │ │ │ │ ├── ToListContainerOptions.java │ │ │ │ └── ToResourceMetadata.java │ │ │ ├── config/ │ │ │ │ ├── BaseSwiftHttpApiModule.java │ │ │ │ ├── SwiftAuthenticationModule.java │ │ │ │ ├── SwiftHttpApiModule.java │ │ │ │ └── SwiftTypeAdapters.java │ │ │ ├── domain/ │ │ │ │ ├── Account.java │ │ │ │ ├── BulkDeleteResponse.java │ │ │ │ ├── Container.java │ │ │ │ ├── DeleteStaticLargeObjectResponse.java │ │ │ │ ├── ExtractArchiveResponse.java │ │ │ │ ├── ObjectList.java │ │ │ │ ├── Segment.java │ │ │ │ └── SwiftObject.java │ │ │ ├── features/ │ │ │ │ ├── AccountApi.java │ │ │ │ ├── BulkApi.java │ │ │ │ ├── ContainerApi.java │ │ │ │ ├── DynamicLargeObjectApi.java │ │ │ │ ├── ObjectApi.java │ │ │ │ └── StaticLargeObjectApi.java │ │ │ ├── functions/ │ │ │ │ ├── ETagHeader.java │ │ │ │ ├── EntriesWithoutMetaPrefix.java │ │ │ │ ├── FalseOnAccepted.java │ │ │ │ ├── MetadataFromHeaders.java │ │ │ │ ├── ParseAccountFromHeaders.java │ │ │ │ ├── ParseContainerFromHeaders.java │ │ │ │ ├── ParseObjectFromResponse.java │ │ │ │ └── ParseObjectListFromResponse.java │ │ │ ├── handlers/ │ │ │ │ └── SwiftErrorHandler.java │ │ │ ├── options/ │ │ │ │ ├── CopyOptions.java │ │ │ │ ├── CreateContainerOptions.java │ │ │ │ ├── ListContainerOptions.java │ │ │ │ ├── PutOptions.java │ │ │ │ └── UpdateContainerOptions.java │ │ │ └── reference/ │ │ │ ├── SwiftHeaders.java │ │ │ └── TempAuthHeaders.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── openstack/ │ │ │ └── swift/ │ │ │ └── v1/ │ │ │ ├── AuthenticationMockTest.java │ │ │ ├── SwiftApiMetadataTest.java │ │ │ ├── SwiftErrorHandlerTest.java │ │ │ ├── TempAuthMockTest.java │ │ │ ├── TemporaryUrlSignerLiveTest.java │ │ │ ├── TemporaryUrlSignerMockTest.java │ │ │ ├── blobstore/ │ │ │ │ ├── RegionScopedBlobStoreContextLiveTest.java │ │ │ │ ├── RegionScopedSwiftBlobStoreParallelLiveTest.java │ │ │ │ └── integration/ │ │ │ │ ├── SwiftBlobIntegrationLiveTest.java │ │ │ │ ├── SwiftBlobLiveTest.java │ │ │ │ ├── SwiftBlobSignerLiveTest.java │ │ │ │ ├── SwiftContainerIntegrationLiveTest.java │ │ │ │ ├── SwiftContainerLiveTest.java │ │ │ │ └── SwiftServiceIntegrationLiveTest.java │ │ │ ├── config/ │ │ │ │ └── SwiftTypeAdaptersTest.java │ │ │ ├── features/ │ │ │ │ ├── AccountApiLiveTest.java │ │ │ │ ├── AccountApiMockTest.java │ │ │ │ ├── BulkApiLiveTest.java │ │ │ │ ├── BulkApiMockTest.java │ │ │ │ ├── ContainerApiLiveTest.java │ │ │ │ ├── ContainerApiMockTest.java │ │ │ │ ├── CreatePublicContainerLiveTest.java │ │ │ │ ├── DynamicLargeObjectApiLiveTest.java │ │ │ │ ├── DynamicLargeObjectApiMockTest.java │ │ │ │ ├── ObjectApiLiveTest.java │ │ │ │ ├── ObjectApiMockTest.java │ │ │ │ ├── StaticLargeObjectApiLiveTest.java │ │ │ │ ├── StaticLargeObjectApiMockTest.java │ │ │ │ └── UrlEncodeAndJoinOnNewlineTest.java │ │ │ ├── internal/ │ │ │ │ └── BaseSwiftApiLiveTest.java │ │ │ └── options/ │ │ │ ├── CreateContainerOptionsTest.java │ │ │ ├── PutOptionsTest.java │ │ │ └── UpdateContainerOptionsTest.java │ │ └── resources/ │ │ ├── access.json │ │ ├── access2.json │ │ ├── container_list.json │ │ ├── logback.xml │ │ ├── manifest_get_response.json │ │ └── object_list.json │ ├── openstack-trove/ │ │ ├── README.md │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── openstack/ │ │ │ └── trove/ │ │ │ └── v1/ │ │ │ ├── TroveApi.java │ │ │ ├── TroveApiMetadata.java │ │ │ ├── binders/ │ │ │ │ ├── BindCreateDatabaseToJson.java │ │ │ │ ├── BindCreateInstanceToJson.java │ │ │ │ ├── BindCreateUserToJson.java │ │ │ │ └── BindGrantUserToJson.java │ │ │ ├── config/ │ │ │ │ ├── TroveHttpApiModule.java │ │ │ │ └── TroveParserModule.java │ │ │ ├── domain/ │ │ │ │ ├── Flavor.java │ │ │ │ ├── Instance.java │ │ │ │ └── User.java │ │ │ ├── features/ │ │ │ │ ├── DatabaseApi.java │ │ │ │ ├── FlavorApi.java │ │ │ │ ├── InstanceApi.java │ │ │ │ └── UserApi.java │ │ │ ├── filters/ │ │ │ │ └── EncodeDotsForUserGet.java │ │ │ ├── functions/ │ │ │ │ ├── ParseDatabaseListForUser.java │ │ │ │ └── ParsePasswordFromRootedInstance.java │ │ │ ├── handlers/ │ │ │ │ └── TroveErrorHandler.java │ │ │ ├── internal/ │ │ │ │ └── Volume.java │ │ │ ├── predicates/ │ │ │ │ └── InstancePredicates.java │ │ │ └── utils/ │ │ │ └── TroveUtils.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── openstack/ │ │ │ └── trove/ │ │ │ └── v1/ │ │ │ ├── domain/ │ │ │ │ ├── FlavorTest.java │ │ │ │ ├── InstanceTest.java │ │ │ │ └── UserTest.java │ │ │ ├── features/ │ │ │ │ ├── DatabaseApiExpectTest.java │ │ │ │ ├── DatabaseApiLiveTest.java │ │ │ │ ├── FlavorApiExpectTest.java │ │ │ │ ├── FlavorApiLiveTest.java │ │ │ │ ├── InstanceApiExpectTest.java │ │ │ │ ├── InstanceApiLiveTest.java │ │ │ │ ├── UserApiExpectTest.java │ │ │ │ └── UserApiLiveTest.java │ │ │ ├── internal/ │ │ │ │ ├── BaseTroveApiExpectTest.java │ │ │ │ ├── BaseTroveApiLiveTest.java │ │ │ │ └── BaseTroveExpectTest.java │ │ │ ├── parse/ │ │ │ │ ├── ParseFlavorListTest.java │ │ │ │ ├── ParseInstanceListTest.java │ │ │ │ └── ParseUserListTest.java │ │ │ └── utils/ │ │ │ └── TroveUtilsExpectTest.java │ │ └── resources/ │ │ ├── access_rax_us.json │ │ ├── database_create_request.json │ │ ├── database_create_simple_request.json │ │ ├── database_list.json │ │ ├── flavor_get.json │ │ ├── flavor_list.json │ │ ├── instance_create.json │ │ ├── instance_create_request.json │ │ ├── instance_get.json │ │ ├── instance_get_bad_instance.json │ │ ├── instance_is_rooted.json │ │ ├── instance_is_rooted_false.json │ │ ├── instance_list.json │ │ ├── instance_root.json │ │ ├── logback-test.xml │ │ ├── logback.xml │ │ ├── trove_user_list.json │ │ ├── user_create_request.json │ │ ├── user_create_simple_request.json │ │ ├── user_create_with_host_simple_request.json │ │ ├── user_get.json │ │ ├── user_get_withhost.json │ │ ├── user_grant_request.json │ │ ├── user_grant_simple_request.json │ │ ├── user_list_access.json │ │ └── user_password_request.json │ ├── pom.xml │ ├── rackspace-clouddns/ │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── rackspace/ │ │ │ └── clouddns/ │ │ │ └── v1/ │ │ │ ├── CloudDNSApi.java │ │ │ ├── CloudDNSApiMetadata.java │ │ │ ├── CloudDNSExceptions.java │ │ │ ├── binders/ │ │ │ │ ├── CreateReverseDNSToJSON.java │ │ │ │ ├── FormatAndContentsToJSON.java │ │ │ │ ├── UpdateDomainsToJSON.java │ │ │ │ ├── UpdateRecordsToJSON.java │ │ │ │ └── UpdateReverseDNSToJSON.java │ │ │ ├── config/ │ │ │ │ ├── CloudDNS.java │ │ │ │ └── CloudDNSHttpApiModule.java │ │ │ ├── domain/ │ │ │ │ ├── CreateDomain.java │ │ │ │ ├── CreateSubdomain.java │ │ │ │ ├── Domain.java │ │ │ │ ├── DomainChange.java │ │ │ │ ├── Job.java │ │ │ │ ├── Record.java │ │ │ │ ├── RecordDetail.java │ │ │ │ ├── Subdomain.java │ │ │ │ └── UpdateDomain.java │ │ │ ├── features/ │ │ │ │ ├── DomainApi.java │ │ │ │ ├── LimitApi.java │ │ │ │ ├── RecordApi.java │ │ │ │ └── ReverseDNSApi.java │ │ │ ├── functions/ │ │ │ │ ├── DomainFunctions.java │ │ │ │ ├── DomainsToPagedIterable.java │ │ │ │ ├── ParseDomain.java │ │ │ │ ├── ParseDomains.java │ │ │ │ ├── ParseJob.java │ │ │ │ ├── ParseOnlyRecord.java │ │ │ │ ├── ParseRecord.java │ │ │ │ ├── ParseRecords.java │ │ │ │ ├── ParseSubdomains.java │ │ │ │ ├── RecordFunctions.java │ │ │ │ ├── RecordsToPagedIterable.java │ │ │ │ └── SubdomainsToPagedIterable.java │ │ │ └── predicates/ │ │ │ └── JobPredicates.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── rackspace/ │ │ │ └── clouddns/ │ │ │ └── v1/ │ │ │ ├── features/ │ │ │ │ ├── CloudDNSApiExpectTest.java │ │ │ │ ├── DomainApiExpectTest.java │ │ │ │ ├── DomainApiLiveTest.java │ │ │ │ ├── LimitApiExpectTest.java │ │ │ │ ├── LimitApiLiveTest.java │ │ │ │ ├── RecordApiExpectTest.java │ │ │ │ ├── RecordApiLiveTest.java │ │ │ │ ├── ReverseDNSApiExpectTest.java │ │ │ │ └── ReverseDNSApiLiveTest.java │ │ │ └── internal/ │ │ │ ├── BaseCloudDNSApiExpectTest.java │ │ │ └── BaseCloudDNSApiLiveTest.java │ │ └── resources/ │ │ ├── domain-create-response.json │ │ ├── domain-create.json │ │ ├── domain-delete.json │ │ ├── domain-export.json │ │ ├── domain-get.json │ │ ├── domain-import-response.json │ │ ├── domain-import.json │ │ ├── domain-list-changes.json │ │ ├── domain-list-page1.json │ │ ├── domain-list-page2.json │ │ ├── domain-list-with-filter.json │ │ ├── domain-list.json │ │ ├── domain-update-email.json │ │ ├── domain-update-response.json │ │ ├── domain-update-ttl.json │ │ ├── domain-update.json │ │ ├── job.json │ │ ├── limit-list.json │ │ ├── limit-types-list.json │ │ ├── logback.xml │ │ ├── record-create-response.json │ │ ├── record-create.json │ │ ├── record-delete.json │ │ ├── record-get.json │ │ ├── record-list-page1.json │ │ ├── record-list-page2.json │ │ ├── record-list-with-filter.json │ │ ├── record-list.json │ │ ├── record-ptr-create-response.json │ │ ├── record-ptr-create.json │ │ ├── record-ptr-delete.json │ │ ├── record-ptr-get.json │ │ ├── record-ptr-list.json │ │ ├── record-ptr-update-response.json │ │ ├── record-ptr-update.json │ │ ├── record-update-response.json │ │ ├── record-update.json │ │ ├── records-delete.json │ │ ├── records-ptr-delete.json │ │ ├── records-update-response.json │ │ ├── records-update.json │ │ ├── subdomain-list-page1.json │ │ ├── subdomain-list-page2.json │ │ └── subdomain-list.json │ ├── rackspace-cloudfiles/ │ │ ├── README.md │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── rackspace/ │ │ │ └── cloudfiles/ │ │ │ └── v1/ │ │ │ ├── CloudFilesApi.java │ │ │ ├── CloudFilesApiMetadata.java │ │ │ ├── binders/ │ │ │ │ └── BindCDNPurgeEmailAddressesToHeaders.java │ │ │ ├── config/ │ │ │ │ └── CloudFilesHttpApiModule.java │ │ │ ├── domain/ │ │ │ │ └── CDNContainer.java │ │ │ ├── features/ │ │ │ │ └── CDNApi.java │ │ │ ├── functions/ │ │ │ │ ├── ParseCDNContainerFromHeaders.java │ │ │ │ ├── ParseCDNContainerURIFromHeaders.java │ │ │ │ └── RegionToCDNEndpoint.java │ │ │ ├── handlers/ │ │ │ │ └── CloudFilesErrorHandler.java │ │ │ ├── options/ │ │ │ │ ├── ListCDNContainerOptions.java │ │ │ │ └── UpdateCDNContainerOptions.java │ │ │ └── reference/ │ │ │ ├── CloudFilesConstants.java │ │ │ └── CloudFilesHeaders.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── rackspace/ │ │ │ └── cloudfiles/ │ │ │ └── v1/ │ │ │ ├── CloudFilesApiLiveTest.java │ │ │ ├── CloudFilesApiMetadataTest.java │ │ │ ├── binders/ │ │ │ │ └── BindCDNPurgeEmailAddressesToHeadersMockTest.java │ │ │ ├── blobstore/ │ │ │ │ ├── CloudFilesRegionScopedBlobStoreContextLiveTest.java │ │ │ │ ├── CloudFilesRegionScopedSwiftBlobStoreParallelLiveTest.java │ │ │ │ └── integration/ │ │ │ │ ├── CloudFilesBlobIntegrationLiveTest.java │ │ │ │ ├── CloudFilesBlobLiveTest.java │ │ │ │ ├── CloudFilesBlobSignerLiveTest.java │ │ │ │ ├── CloudFilesContainerIntegrationLiveTest.java │ │ │ │ ├── CloudFilesContainerLiveTest.java │ │ │ │ └── CloudFilesServiceIntegrationLiveTest.java │ │ │ ├── features/ │ │ │ │ ├── CloudFilesAccountApiLiveTest.java │ │ │ │ ├── CloudFilesBulkApiLiveTest.java │ │ │ │ ├── CloudFilesCDNApiLiveTest.java │ │ │ │ ├── CloudFilesCDNApiMockTest.java │ │ │ │ ├── CloudFilesContainerApiLiveTest.java │ │ │ │ ├── CloudFilesDynamicLargeObjectApiLiveTest.java │ │ │ │ ├── CloudFilesObjectApiLiveTest.java │ │ │ │ └── CloudFilesStaticLargeObjectApiLiveTest.java │ │ │ ├── internal/ │ │ │ │ └── BaseCloudFilesApiLiveTest.java │ │ │ └── options/ │ │ │ └── UpdateCDNContainerOptionsTest.java │ │ └── resources/ │ │ ├── cdn_container_list.json │ │ ├── cdn_container_list_at.json │ │ └── logback.xml │ ├── rackspace-cloudidentity/ │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── rackspace/ │ │ │ └── cloudidentity/ │ │ │ └── v2_0/ │ │ │ ├── CloudIdentityApiMetadata.java │ │ │ ├── CloudIdentityAuthenticationApi.java │ │ │ ├── ServiceType.java │ │ │ ├── config/ │ │ │ │ ├── CloudIdentityAuthenticationModule.java │ │ │ │ └── CloudIdentityCredentialTypes.java │ │ │ ├── domain/ │ │ │ │ └── ApiKeyCredentials.java │ │ │ └── functions/ │ │ │ ├── AuthenticateApiKeyCredentials.java │ │ │ └── DateParser.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── rackspace/ │ │ │ └── cloudidentity/ │ │ │ └── v2_0/ │ │ │ ├── CloudIdentityApiLiveTest.java │ │ │ ├── CloudIdentityApiMetadataTest.java │ │ │ ├── features/ │ │ │ │ └── CloudIdentityServiceApiLiveTest.java │ │ │ └── internal/ │ │ │ └── RackspaceFixture.java │ │ └── resources/ │ │ └── rackspaceAuthResponse.json │ ├── rackspace-cloudloadbalancers/ │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── rackspace/ │ │ │ └── cloudloadbalancers/ │ │ │ └── v1/ │ │ │ ├── CloudLoadBalancersApi.java │ │ │ ├── CloudLoadBalancersApiMetadata.java │ │ │ ├── binders/ │ │ │ │ └── BindMetadataToJsonPayload.java │ │ │ ├── config/ │ │ │ │ └── CloudLoadBalancersHttpApiModule.java │ │ │ ├── domain/ │ │ │ │ ├── AccessRule.java │ │ │ │ ├── AccessRuleWithId.java │ │ │ │ ├── AccountUsage.java │ │ │ │ ├── AddNode.java │ │ │ │ ├── ConnectionThrottle.java │ │ │ │ ├── CreateLoadBalancer.java │ │ │ │ ├── HealthMonitor.java │ │ │ │ ├── HistoricalUsage.java │ │ │ │ ├── LoadBalancer.java │ │ │ │ ├── LoadBalancerInfo.java │ │ │ │ ├── LoadBalancerStats.java │ │ │ │ ├── LoadBalancerUsage.java │ │ │ │ ├── Metadata.java │ │ │ │ ├── Node.java │ │ │ │ ├── Protocol.java │ │ │ │ ├── SSLTermination.java │ │ │ │ ├── SessionPersistence.java │ │ │ │ ├── SourceAddresses.java │ │ │ │ ├── UpdateLoadBalancer.java │ │ │ │ ├── UpdateNode.java │ │ │ │ ├── VirtualIP.java │ │ │ │ ├── VirtualIPWithId.java │ │ │ │ └── internal/ │ │ │ │ ├── BaseLoadBalancer.java │ │ │ │ └── BaseNode.java │ │ │ ├── features/ │ │ │ │ ├── AccessRuleApi.java │ │ │ │ ├── ConnectionApi.java │ │ │ │ ├── ContentCachingApi.java │ │ │ │ ├── ErrorPageApi.java │ │ │ │ ├── HealthMonitorApi.java │ │ │ │ ├── LoadBalancerApi.java │ │ │ │ ├── NodeApi.java │ │ │ │ ├── ReportApi.java │ │ │ │ ├── SSLTerminationApi.java │ │ │ │ ├── SessionPersistenceApi.java │ │ │ │ └── VirtualIPApi.java │ │ │ ├── functions/ │ │ │ │ ├── ConvertLB.java │ │ │ │ ├── DateParser.java │ │ │ │ ├── LB.java │ │ │ │ ├── ParseAlgorithms.java │ │ │ │ ├── ParseLoadBalancer.java │ │ │ │ ├── ParseLoadBalancerUsages.java │ │ │ │ ├── ParseLoadBalancers.java │ │ │ │ ├── ParseMetadata.java │ │ │ │ ├── ParseNestedBoolean.java │ │ │ │ ├── ParseNestedString.java │ │ │ │ ├── ParseNode.java │ │ │ │ ├── ParseNodes.java │ │ │ │ └── ParseSessionPersistence.java │ │ │ ├── handlers/ │ │ │ │ └── ParseCloudLoadBalancersErrorFromHttpResponse.java │ │ │ ├── loadbalancer/ │ │ │ │ ├── config/ │ │ │ │ │ ├── CloudLoadBalancersBindLoadBalancerStrategiesByClass.java │ │ │ │ │ ├── CloudLoadBalancersLoadBalancerContextModule.java │ │ │ │ │ └── CloudLoadBalancersLoadBalancerServiceDependenciesModule.java │ │ │ │ ├── functions/ │ │ │ │ │ └── LoadBalancerToLoadBalancerMetadata.java │ │ │ │ └── strategy/ │ │ │ │ ├── CloudLoadBalancersDestroyLoadBalancerStrategy.java │ │ │ │ ├── CloudLoadBalancersGetLoadBalancerMetadataStrategy.java │ │ │ │ ├── CloudLoadBalancersListLoadBalancersStrategy.java │ │ │ │ └── CloudLoadBalancersLoadBalanceNodesStrategy.java │ │ │ ├── options/ │ │ │ │ └── ListOptions.java │ │ │ └── predicates/ │ │ │ └── LoadBalancerPredicates.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── rackspace/ │ │ │ └── cloudloadbalancers/ │ │ │ └── v1/ │ │ │ ├── CloudLoadBalancersApiMetadataTest.java │ │ │ ├── features/ │ │ │ │ ├── AccessRuleApiExpectTest.java │ │ │ │ ├── AccessRuleApiLiveTest.java │ │ │ │ ├── ConnectionApiExpectTest.java │ │ │ │ ├── ConnectionApiLiveTest.java │ │ │ │ ├── ContentCachingApiExpectTest.java │ │ │ │ ├── ContentCachingApiLiveTest.java │ │ │ │ ├── ErrorPageApiExpectTest.java │ │ │ │ ├── ErrorPageApiLiveTest.java │ │ │ │ ├── HealthMonitorApiExpectTest.java │ │ │ │ ├── HealthMonitorApiLiveTest.java │ │ │ │ ├── LoadBalancerApiExpectTest.java │ │ │ │ ├── LoadBalancerApiLiveTest.java │ │ │ │ ├── NodeApiExpectTest.java │ │ │ │ ├── NodeApiLiveTest.java │ │ │ │ ├── ReportApiExpectTest.java │ │ │ │ ├── ReportApiLiveTest.java │ │ │ │ ├── SSLTerminationApiExpectTest.java │ │ │ │ ├── SSLTerminationApiLiveTest.java │ │ │ │ ├── SessionPersistenceApiExpectTest.java │ │ │ │ ├── SessionPersistenceApiLiveTest.java │ │ │ │ ├── VirtualIPApiExpectTest.java │ │ │ │ └── VirtualIPApiLiveTest.java │ │ │ ├── functions/ │ │ │ │ ├── ParseLoadBalancerTest.java │ │ │ │ ├── ParseLoadBalancerWhenDeletedTest.java │ │ │ │ └── ParseLoadBalancersTest.java │ │ │ ├── handlers/ │ │ │ │ └── ParseCloudLoadBalancersErrorFromHttpResponseTest.java │ │ │ ├── internal/ │ │ │ │ ├── BaseCloudLoadBalancerApiExpectTest.java │ │ │ │ └── BaseCloudLoadBalancersApiLiveTest.java │ │ │ └── options/ │ │ │ └── ListOptionsTest.java │ │ └── resources/ │ │ ├── accesslist-create.json │ │ ├── accesslist-list.json │ │ ├── connectionlogging-disable.json │ │ ├── connectionlogging-enable.json │ │ ├── connectionthrottle-create.json │ │ ├── connectionthrottle-get-deleted.json │ │ ├── connectionthrottle-get.json │ │ ├── contentcaching-disable.json │ │ ├── contentcaching-enable.json │ │ ├── errorpage.html │ │ ├── healthmonitor-create.json │ │ ├── healthmonitor-get-deleted.json │ │ ├── healthmonitor-get.json │ │ ├── loadbalancer-create.json │ │ ├── loadbalancer-get-deleted.json │ │ ├── loadbalancer-get.json │ │ ├── loadbalancer-update.json │ │ ├── loadbalancers-list.json │ │ ├── metadata-create.json │ │ ├── metadata-list.json │ │ ├── node-get.json │ │ ├── node-update.json │ │ ├── nodes-add.json │ │ ├── nodes-list.json │ │ ├── report-algorithms-list.json │ │ ├── report-billable-list.json │ │ ├── report-historical-get.json │ │ ├── report-loadbalancerstats-get.json │ │ ├── report-loadbalancerusage-list.json │ │ ├── report-protocols-list.json │ │ ├── sessionpersistence-create.json │ │ ├── sessionpersistence-get-deleted.json │ │ ├── sessionpersistence-get.json │ │ ├── ssltermination-certificate.txt │ │ ├── ssltermination-create.json │ │ ├── ssltermination-get.json │ │ ├── ssltermination-intermediatecertificate.txt │ │ ├── ssltermination-privatekey.txt │ │ ├── virtualips-create-response.json │ │ ├── virtualips-create.json │ │ └── virtualips-list.json │ ├── route53/ │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── route53/ │ │ │ ├── InvalidChangeBatchException.java │ │ │ ├── Route53Api.java │ │ │ ├── Route53ApiMetadata.java │ │ │ ├── binders/ │ │ │ │ ├── BindChangeBatch.java │ │ │ │ └── BindNextRecord.java │ │ │ ├── config/ │ │ │ │ └── Route53HttpApiModule.java │ │ │ ├── domain/ │ │ │ │ ├── Change.java │ │ │ │ ├── ChangeBatch.java │ │ │ │ ├── HostedZone.java │ │ │ │ ├── HostedZoneAndNameServers.java │ │ │ │ ├── NewHostedZone.java │ │ │ │ ├── ResourceRecordSet.java │ │ │ │ └── ResourceRecordSetIterable.java │ │ │ ├── features/ │ │ │ │ ├── HostedZoneApi.java │ │ │ │ └── ResourceRecordSetApi.java │ │ │ ├── filters/ │ │ │ │ └── RestAuthentication.java │ │ │ ├── functions/ │ │ │ │ ├── HostedZonesToPagedIterable.java │ │ │ │ ├── ResourceRecordSetIterableToPagedIterable.java │ │ │ │ └── SerializeRRS.java │ │ │ ├── handlers/ │ │ │ │ └── Route53ErrorHandler.java │ │ │ ├── predicates/ │ │ │ │ ├── HostedZonePredicates.java │ │ │ │ └── ResourceRecordSetPredicates.java │ │ │ └── xml/ │ │ │ ├── ChangeHandler.java │ │ │ ├── CreateHostedZoneResponseHandler.java │ │ │ ├── GetHostedZoneResponseHandler.java │ │ │ ├── HostedZoneHandler.java │ │ │ ├── InvalidChangeBatchHandler.java │ │ │ ├── ListHostedZonesResponseHandler.java │ │ │ ├── ListResourceRecordSetsResponseHandler.java │ │ │ └── ResourceRecordSetHandler.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── route53/ │ │ │ ├── Route53ApiExpectTest.java │ │ │ ├── Route53ApiLiveTest.java │ │ │ ├── Route53ApiMetadataTest.java │ │ │ ├── features/ │ │ │ │ ├── HostedZoneApiExpectTest.java │ │ │ │ ├── HostedZoneApiLiveTest.java │ │ │ │ ├── ResourceRecordSetApiExpectTest.java │ │ │ │ └── ResourceRecordSetApiLiveTest.java │ │ │ ├── functions/ │ │ │ │ └── SerializeRRSTest.java │ │ │ ├── handlers/ │ │ │ │ └── Route53ErrorHandlerTest.java │ │ │ ├── internal/ │ │ │ │ ├── BaseRoute53ApiExpectTest.java │ │ │ │ ├── BaseRoute53ApiLiveTest.java │ │ │ │ └── BaseRoute53ExpectTest.java │ │ │ ├── parse/ │ │ │ │ ├── CreateHostedZoneResponseTest.java │ │ │ │ ├── GetChangeResponseTest.java │ │ │ │ ├── GetHostedZoneResponseTest.java │ │ │ │ ├── InvalidChangeBatchResponseTest.java │ │ │ │ ├── ListHostedZonesResponseTest.java │ │ │ │ └── ListResourceRecordSetsResponseTest.java │ │ │ └── predicates/ │ │ │ ├── HostedZonePredicatesTest.java │ │ │ └── ResourceRecordSetPredicatesTest.java │ │ └── resources/ │ │ ├── batch_rrs_request.xml │ │ ├── change.xml │ │ ├── create_hosted_zone.xml │ │ ├── create_rrs_request.xml │ │ ├── delete_rrs_request.xml │ │ ├── hosted_zone.xml │ │ ├── hosted_zones.xml │ │ ├── invalid_change_batch.xml │ │ ├── logback.xml │ │ ├── new_zone.xml │ │ └── rrsets.xml │ ├── s3/ │ │ ├── README.txt │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── s3/ │ │ │ ├── Bucket.java │ │ │ ├── S3.java │ │ │ ├── S3ApiMetadata.java │ │ │ ├── S3Client.java │ │ │ ├── S3Fallbacks.java │ │ │ ├── binders/ │ │ │ │ ├── BindACLToXMLPayload.java │ │ │ │ ├── BindAsHostPrefixIfConfigured.java │ │ │ │ ├── BindBucketLoggingToXmlPayload.java │ │ │ │ ├── BindCannedAclToRequest.java │ │ │ │ ├── BindIterableAsPayloadToDeleteRequest.java │ │ │ │ ├── BindNoBucketLoggingToXmlPayload.java │ │ │ │ ├── BindObjectMetadataToRequest.java │ │ │ │ ├── BindOwnershipControlsToXMLPayload.java │ │ │ │ ├── BindPartIdsAndETagsToRequest.java │ │ │ │ ├── BindPayerToXmlPayload.java │ │ │ │ ├── BindPublicAccessBlockConfigurationToXMLPayload.java │ │ │ │ ├── BindS3ObjectMetadataToRequest.java │ │ │ │ └── XMLHelper.java │ │ │ ├── blobstore/ │ │ │ │ ├── S3BlobRequestSigner.java │ │ │ │ ├── S3BlobStore.java │ │ │ │ ├── S3BlobStoreContext.java │ │ │ │ ├── config/ │ │ │ │ │ └── S3BlobStoreContextModule.java │ │ │ │ ├── functions/ │ │ │ │ │ ├── BlobToObject.java │ │ │ │ │ ├── BlobToObjectMetadata.java │ │ │ │ │ ├── BucketToResourceList.java │ │ │ │ │ ├── BucketToResourceMetadata.java │ │ │ │ │ ├── BucketsToStorageMetadata.java │ │ │ │ │ ├── CommonPrefixesToResourceMetadata.java │ │ │ │ │ ├── ContainerToBucketListOptions.java │ │ │ │ │ ├── LocationFromBucketName.java │ │ │ │ │ ├── ObjectToBlob.java │ │ │ │ │ └── ObjectToBlobMetadata.java │ │ │ │ ├── internal/ │ │ │ │ │ ├── BackoffOnNotFoundWhenGetBucketACL.java │ │ │ │ │ └── S3BlobStoreContextImpl.java │ │ │ │ └── strategy/ │ │ │ │ └── MultipartUpload.java │ │ │ ├── config/ │ │ │ │ ├── S3HttpApiModule.java │ │ │ │ ├── S3ObjectModule.java │ │ │ │ ├── S3ParserModule.java │ │ │ │ └── package-info.java │ │ │ ├── domain/ │ │ │ │ ├── AccessControlList.java │ │ │ │ ├── BucketLogging.java │ │ │ │ ├── BucketMetadata.java │ │ │ │ ├── CannedAccessPolicy.java │ │ │ │ ├── CanonicalUser.java │ │ │ │ ├── DeleteResult.java │ │ │ │ ├── ListBucketResponse.java │ │ │ │ ├── ListMultipartUploadResponse.java │ │ │ │ ├── ListMultipartUploadsResponse.java │ │ │ │ ├── MutableObjectMetadata.java │ │ │ │ ├── ObjectMetadata.java │ │ │ │ ├── ObjectMetadataBuilder.java │ │ │ │ ├── Payer.java │ │ │ │ ├── PublicAccessBlockConfiguration.java │ │ │ │ ├── S3Object.java │ │ │ │ ├── internal/ │ │ │ │ │ ├── BucketListObjectMetadata.java │ │ │ │ │ ├── CopyObjectResult.java │ │ │ │ │ ├── ListBucketResponseImpl.java │ │ │ │ │ ├── MutableObjectMetadataImpl.java │ │ │ │ │ └── S3ObjectImpl.java │ │ │ │ └── package-info.java │ │ │ ├── fallbacks/ │ │ │ │ └── FalseIfBucketAlreadyOwnedByYouOrOperationAbortedWhenBucketExists.java │ │ │ ├── filters/ │ │ │ │ ├── Aws4SignerBase.java │ │ │ │ ├── Aws4SignerForAuthorizationHeader.java │ │ │ │ ├── Aws4SignerForChunkedUpload.java │ │ │ │ ├── Aws4SignerForQueryString.java │ │ │ │ ├── AwsHostNameUtils.java │ │ │ │ ├── AwsSignatureV4Constants.java │ │ │ │ ├── ChunkedUploadException.java │ │ │ │ ├── ChunkedUploadPayload.java │ │ │ │ ├── RequestAuthorizeSignature.java │ │ │ │ ├── RequestAuthorizeSignatureV2.java │ │ │ │ ├── RequestAuthorizeSignatureV4.java │ │ │ │ └── package-info.java │ │ │ ├── functions/ │ │ │ │ ├── AssignCorrectHostnameForBucket.java │ │ │ │ ├── BindRegionToXmlPayload.java │ │ │ │ ├── DefaultEndpointThenInvalidateRegion.java │ │ │ │ ├── ETagFromHttpResponseViaRegex.java │ │ │ │ ├── GetRegionForBucket.java │ │ │ │ ├── ObjectKey.java │ │ │ │ ├── ObjectMetadataKey.java │ │ │ │ ├── ParseObjectFromHeadersAndHttpContent.java │ │ │ │ ├── ParseObjectMetadataFromHeaders.java │ │ │ │ ├── UploadIdFromHttpResponseViaRegex.java │ │ │ │ └── package-info.java │ │ │ ├── handlers/ │ │ │ │ ├── ParseS3ErrorFromXmlContent.java │ │ │ │ └── S3RedirectionRetryHandler.java │ │ │ ├── options/ │ │ │ │ ├── CopyObjectOptions.java │ │ │ │ ├── ListBucketOptions.java │ │ │ │ ├── PutBucketOptions.java │ │ │ │ ├── PutObjectOptions.java │ │ │ │ └── package-info.java │ │ │ ├── package-info.java │ │ │ ├── predicates/ │ │ │ │ └── validators/ │ │ │ │ └── BucketNameValidator.java │ │ │ ├── reference/ │ │ │ │ ├── S3Constants.java │ │ │ │ ├── S3Headers.java │ │ │ │ └── package-info.java │ │ │ ├── util/ │ │ │ │ ├── S3Utils.java │ │ │ │ └── package-info.java │ │ │ └── xml/ │ │ │ ├── AccessControlListHandler.java │ │ │ ├── BucketLoggingHandler.java │ │ │ ├── CopyObjectHandler.java │ │ │ ├── DeleteResultHandler.java │ │ │ ├── ErrorEntryHandler.java │ │ │ ├── ListAllMyBucketsHandler.java │ │ │ ├── ListBucketHandler.java │ │ │ ├── ListMultipartUploadsHandler.java │ │ │ ├── LocationConstraintHandler.java │ │ │ ├── PartIdsFromHttpResponse.java │ │ │ ├── PartIdsFromHttpResponseFull.java │ │ │ ├── PayerHandler.java │ │ │ └── package-info.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── s3/ │ │ │ ├── PathBasedS3ClientExpectTest.java │ │ │ ├── S3ApiMetadataTest.java │ │ │ ├── S3ClientExpectTest.java │ │ │ ├── S3ClientLiveTest.java │ │ │ ├── S3ClientMockTest.java │ │ │ ├── S3ClientTest.java │ │ │ ├── S3Test.java │ │ │ ├── binders/ │ │ │ │ ├── BindACLToXMLPayloadTest.java │ │ │ │ ├── BindAsHostPrefixIfConfiguredNoPathTest.java │ │ │ │ ├── BindAsHostPrefixIfConfiguredTest.java │ │ │ │ ├── BindBucketLoggingToXmlPayloadTest.java │ │ │ │ ├── BindIterableAsPayloadToDeleteRequestTest.java │ │ │ │ ├── BindNoBucketLoggingToXmlPayloadTest.java │ │ │ │ ├── BindObjectMetadataToRequestTest.java │ │ │ │ ├── BindPartIdsAndETagsToRequestTest.java │ │ │ │ └── BindS3ObjectMetadataToRequestTest.java │ │ │ ├── blobstore/ │ │ │ │ ├── S3BlobSignerExpectTest.java │ │ │ │ ├── functions/ │ │ │ │ │ ├── BlobToHttpGetOptionsTest.java │ │ │ │ │ ├── BucketToContainerListOptions.java │ │ │ │ │ ├── BucketsToStorageMetadataTest.java │ │ │ │ │ ├── LocationFromBucketNameTest.java │ │ │ │ │ └── ResourceToBucketList.java │ │ │ │ ├── integration/ │ │ │ │ │ ├── S3BlobIntegrationLiveTest.java │ │ │ │ │ ├── S3BlobLiveTest.java │ │ │ │ │ ├── S3BlobSignerLiveTest.java │ │ │ │ │ ├── S3ContainerIntegrationLiveTest.java │ │ │ │ │ ├── S3ContainerLiveTest.java │ │ │ │ │ └── S3ServiceIntegrationLiveTest.java │ │ │ │ └── internal/ │ │ │ │ └── BackoffOnNotFoundWhenGetBucketACLTest.java │ │ │ ├── fallbacks/ │ │ │ │ └── FalseIfBucketAlreadyOwnedByYouOrOperationAbortedWhenBucketExistsTest.java │ │ │ ├── filters/ │ │ │ │ ├── AwsHostNameUtilsTest.java │ │ │ │ ├── RequestAuthorizeSignatureV2Test.java │ │ │ │ ├── RequestAuthorizeSignatureV4ChunkedUploadTest.java │ │ │ │ ├── RequestAuthorizeSignatureV4Test.java │ │ │ │ └── RequestAuthorizeSignatureWithSessionCredentialsTest.java │ │ │ ├── functions/ │ │ │ │ ├── AssignCorrectHostnameForBucketTest.java │ │ │ │ ├── DefaultEndpointThenInvalidateRegionTest.java │ │ │ │ ├── ETagFromHttpResponseViaRegexTest.java │ │ │ │ ├── GetRegionForBucketTest.java │ │ │ │ ├── ParseObjectMetadataFromHeadersTest.java │ │ │ │ └── UploadIdFromHttpResponseViaRegexTest.java │ │ │ ├── handlers/ │ │ │ │ └── ParseS3ErrorFromXmlContentTest.java │ │ │ ├── internal/ │ │ │ │ ├── BaseS3ClientExpectTest.java │ │ │ │ └── BaseS3ClientTest.java │ │ │ ├── options/ │ │ │ │ ├── CopyObjectOptionsTest.java │ │ │ │ ├── ListBucketOptionsTest.java │ │ │ │ ├── PutBucketOptionsTest.java │ │ │ │ └── PutObjectOptionsTest.java │ │ │ ├── services/ │ │ │ │ └── BucketsLiveTest.java │ │ │ └── xml/ │ │ │ ├── AccessControlListHandlerTest.java │ │ │ ├── BucketLoggingHandlerTest.java │ │ │ ├── CopyObjectHandlerTest.java │ │ │ ├── DeleteResultHandlerTest.java │ │ │ ├── ListBucketHandlerTest.java │ │ │ ├── PartIdsFromHttpResponseTest.java │ │ │ ├── PayerHandlerTest.java │ │ │ └── S3ParserTest.java │ │ └── resources/ │ │ ├── acl_to_xml.xml │ │ ├── bucket_logging.xml │ │ ├── complete-multipart-upload.xml │ │ ├── copy_object.xml │ │ ├── delete-result.xml │ │ ├── initiate-multipart-upload.xml │ │ ├── list_bucket.xml │ │ ├── log4j.xml │ │ └── multipart-upload-list-parts.xml │ ├── sqs/ │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── sqs/ │ │ │ ├── SQS.java │ │ │ ├── SQSApi.java │ │ │ ├── SQSApiMetadata.java │ │ │ ├── binders/ │ │ │ │ ├── BindAttributeNamesToIndexedFormParams.java │ │ │ │ ├── BindChangeMessageVisibilityBatchRequestEntryToIndexedFormParams.java │ │ │ │ ├── BindDeleteMessageBatchRequestEntryToIndexedFormParams.java │ │ │ │ ├── BindSendMessageBatchRequestEntryToIndexedFormParams.java │ │ │ │ └── BindSendMessageBatchRequestEntryWithDelaysToIndexedFormParams.java │ │ │ ├── config/ │ │ │ │ ├── SQSHttpApiModule.java │ │ │ │ └── SQSProperties.java │ │ │ ├── domain/ │ │ │ │ ├── Action.java │ │ │ │ ├── Attribute.java │ │ │ │ ├── BatchError.java │ │ │ │ ├── BatchResult.java │ │ │ │ ├── Message.java │ │ │ │ ├── MessageIdAndMD5.java │ │ │ │ └── QueueAttributes.java │ │ │ ├── features/ │ │ │ │ ├── MessageApi.java │ │ │ │ ├── Messages.java │ │ │ │ ├── PermissionApi.java │ │ │ │ └── QueueApi.java │ │ │ ├── functions/ │ │ │ │ └── MapToQueueAttributes.java │ │ │ ├── handlers/ │ │ │ │ ├── ParseSQSErrorFromXmlContent.java │ │ │ │ └── SQSErrorRetryHandler.java │ │ │ ├── options/ │ │ │ │ ├── CreateQueueOptions.java │ │ │ │ ├── ListQueuesOptions.java │ │ │ │ ├── ReceiveMessageOptions.java │ │ │ │ └── SendMessageOptions.java │ │ │ ├── package-info.java │ │ │ ├── reference/ │ │ │ │ ├── SQSParameters.java │ │ │ │ └── package-info.java │ │ │ └── xml/ │ │ │ ├── AttributesHandler.java │ │ │ ├── BatchErrorHandler.java │ │ │ ├── BatchResponseHandler.java │ │ │ ├── ChangeMessageVisibilityBatchResponseHandler.java │ │ │ ├── DeleteMessageBatchResponseHandler.java │ │ │ ├── IdHandler.java │ │ │ ├── MessageHandler.java │ │ │ ├── ReceiveMessageResponseHandler.java │ │ │ ├── RegexListQueuesResponseHandler.java │ │ │ ├── RegexMessageIdAndMD5Handler.java │ │ │ ├── RegexQueueHandler.java │ │ │ ├── SendMessageBatchResponseHandler.java │ │ │ ├── SendMessageBatchResultEntryHandler.java │ │ │ ├── TextFromSingleElementHandler.java │ │ │ ├── ValueHandler.java │ │ │ └── internal/ │ │ │ └── BaseRegexQueueHandler.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── sqs/ │ │ │ ├── SQSApiMetadataTest.java │ │ │ ├── SQSTest.java │ │ │ ├── features/ │ │ │ │ ├── BulkMessageApiLiveTest.java │ │ │ │ ├── MessageApiExpectTest.java │ │ │ │ ├── MessageApiLiveTest.java │ │ │ │ ├── PermissionApiExpectTest.java │ │ │ │ ├── PermissionApiLiveTest.java │ │ │ │ ├── QueueApiExpectTest.java │ │ │ │ └── QueueApiLiveTest.java │ │ │ ├── functions/ │ │ │ │ └── MapToQueueAttributesTest.java │ │ │ ├── handlers/ │ │ │ │ └── SQSErrorRetryHandlerTest.java │ │ │ ├── internal/ │ │ │ │ ├── BaseSQSApiExpectTest.java │ │ │ │ ├── BaseSQSApiLiveTest.java │ │ │ │ └── BaseSQSExpectTest.java │ │ │ ├── options/ │ │ │ │ ├── CreateQueueOptionsTest.java │ │ │ │ ├── ListQueuesOptionsTest.java │ │ │ │ ├── ReceiveMessageOptionsTest.java │ │ │ │ └── SendMessageOptionsTest.java │ │ │ └── parse/ │ │ │ ├── ChangeMessageVisibilityBatchResponseTest.java │ │ │ ├── CreateQueueResponseTest.java │ │ │ ├── DeleteMessageBatchResponseTest.java │ │ │ ├── GetQueueAttributesResponseTest.java │ │ │ ├── ReceiveMessageResponseTest.java │ │ │ ├── SendMessageBatchResponseTest.java │ │ │ └── SendMessageResponseTest.java │ │ └── resources/ │ │ ├── attributes.xml │ │ ├── change_message_visibility_batch.xml │ │ ├── create_queue.xml │ │ ├── delete_message_batch.xml │ │ ├── get_queue_url.xml │ │ ├── list_queues.xml │ │ ├── log4j.xml │ │ ├── messages.xml │ │ ├── send_message.xml │ │ └── send_message_batch.xml │ └── sts/ │ ├── bnd.bnd │ ├── pom.xml │ └── src/ │ ├── main/ │ │ └── java/ │ │ └── org/ │ │ └── jclouds/ │ │ ├── aws/ │ │ │ ├── AWSResponseException.java │ │ │ ├── binders/ │ │ │ │ ├── BindMapToIndexedFormParams.java │ │ │ │ └── BindTableToIndexedFormParams.java │ │ │ ├── config/ │ │ │ │ ├── AWSHttpApiModule.java │ │ │ │ └── FormSigningHttpApiModule.java │ │ │ ├── domain/ │ │ │ │ ├── AWSError.java │ │ │ │ ├── Region.java │ │ │ │ └── SessionCredentials.java │ │ │ ├── filters/ │ │ │ │ ├── FormSigner.java │ │ │ │ ├── FormSignerUtils.java │ │ │ │ └── FormSignerV4.java │ │ │ ├── handlers/ │ │ │ │ ├── AWSClientErrorRetryHandler.java │ │ │ │ ├── AWSServerErrorRetryHandler.java │ │ │ │ ├── ParseAWSErrorFromXmlContent.java │ │ │ │ └── package-info.java │ │ │ ├── reference/ │ │ │ │ ├── AWSConstants.java │ │ │ │ └── FormParameters.java │ │ │ ├── util/ │ │ │ │ └── AWSUtils.java │ │ │ └── xml/ │ │ │ ├── ErrorHandler.java │ │ │ └── SessionCredentialsHandler.java │ │ └── sts/ │ │ ├── STSApi.java │ │ ├── STSApiMetadata.java │ │ ├── config/ │ │ │ └── STSHttpApiModule.java │ │ ├── domain/ │ │ │ ├── User.java │ │ │ └── UserAndSessionCredentials.java │ │ ├── options/ │ │ │ ├── AssumeRoleOptions.java │ │ │ ├── FederatedUserOptions.java │ │ │ └── SessionCredentialsOptions.java │ │ └── xml/ │ │ └── UserAndSessionCredentialsHandler.java │ └── test/ │ ├── java/ │ │ └── org/ │ │ └── jclouds/ │ │ ├── aws/ │ │ │ ├── filters/ │ │ │ │ ├── FormSignerV2Test.java │ │ │ │ ├── FormSignerV4LiveTest.java │ │ │ │ └── FormSignerV4Test.java │ │ │ ├── handlers/ │ │ │ │ ├── AWSClientErrorRetryHandlerTest.java │ │ │ │ ├── AWSServerErrorRetryHandlerTest.java │ │ │ │ └── ParseAWSErrorFromXmlContentTest.java │ │ │ ├── util/ │ │ │ │ └── AWSUtilsTest.java │ │ │ └── xml/ │ │ │ ├── ErrorHandlerTest.java │ │ │ └── SessionCredentialsHandlerTest.java │ │ └── sts/ │ │ ├── STSApiExpectTest.java │ │ ├── STSApiLiveTest.java │ │ ├── STSApiMetadataTest.java │ │ ├── internal/ │ │ │ ├── BaseSTSApiExpectTest.java │ │ │ ├── BaseSTSApiLiveTest.java │ │ │ └── BaseSTSExpectTest.java │ │ ├── options/ │ │ │ ├── AssumeRoleOptionsTest.java │ │ │ ├── FederatedUserOptionsTest.java │ │ │ └── SessionCredentialsOptionsTest.java │ │ └── parse/ │ │ ├── AssumeRoleResponseTest.java │ │ ├── GetFederationTokenResponseTest.java │ │ └── GetSessionTokenResponseTest.java │ └── resources/ │ ├── assume_role.xml │ ├── credentials.xml │ ├── error.xml │ ├── federation_token.xml │ ├── log4j.xml │ └── session_token.xml ├── blobstore/ │ ├── bnd.bnd │ ├── pom.xml │ └── src/ │ ├── main/ │ │ └── java/ │ │ └── org/ │ │ └── jclouds/ │ │ └── blobstore/ │ │ ├── BlobRequestSigner.java │ │ ├── BlobStore.java │ │ ├── BlobStoreContext.java │ │ ├── BlobStoreFallbacks.java │ │ ├── BlobStores.java │ │ ├── ContainerNotFoundException.java │ │ ├── KeyAlreadyExistsException.java │ │ ├── KeyNotFoundException.java │ │ ├── LocalBlobRequestSigner.java │ │ ├── LocalStorageStrategy.java │ │ ├── TransientApiMetadata.java │ │ ├── TransientStorageStrategy.java │ │ ├── attr/ │ │ │ ├── BlobCapabilities.java │ │ │ ├── BlobCapability.java │ │ │ ├── BlobScope.java │ │ │ ├── BlobScopes.java │ │ │ ├── Charge.java │ │ │ ├── Charges.java │ │ │ ├── ConsistencyModel.java │ │ │ ├── ContainerCapabilities.java │ │ │ ├── ContainerCapability.java │ │ │ ├── ContainerVisibilities.java │ │ │ ├── ContainerVisibility.java │ │ │ └── FolderCapability.java │ │ ├── binders/ │ │ │ ├── BindBlobToMultipartForm.java │ │ │ ├── BindMapToHeadersWithPrefix.java │ │ │ └── BindUserMetadataToHeadersWithPrefix.java │ │ ├── config/ │ │ │ ├── BlobStoreObjectModule.java │ │ │ ├── LocalBlobStore.java │ │ │ └── TransientBlobStoreContextModule.java │ │ ├── domain/ │ │ │ ├── Blob.java │ │ │ ├── BlobAccess.java │ │ │ ├── BlobBuilder.java │ │ │ ├── BlobMetadata.java │ │ │ ├── ContainerAccess.java │ │ │ ├── MultipartPart.java │ │ │ ├── MultipartUpload.java │ │ │ ├── MutableBlobMetadata.java │ │ │ ├── MutableStorageMetadata.java │ │ │ ├── PageSet.java │ │ │ ├── StorageMetadata.java │ │ │ ├── StorageType.java │ │ │ ├── Tier.java │ │ │ └── internal/ │ │ │ ├── BlobBuilderImpl.java │ │ │ ├── BlobImpl.java │ │ │ ├── BlobMetadataImpl.java │ │ │ ├── MutableBlobMetadataImpl.java │ │ │ ├── MutableStorageMetadataImpl.java │ │ │ ├── PageSetImpl.java │ │ │ └── StorageMetadataImpl.java │ │ ├── functions/ │ │ │ ├── BlobName.java │ │ │ ├── BlobToHttpGetOptions.java │ │ │ ├── HttpGetOptionsListToGetOptions.java │ │ │ ├── ParseBlobFromHeadersAndHttpContent.java │ │ │ ├── ParseSystemAndUserMetadataFromHeaders.java │ │ │ ├── PrefixToResourceMetadata.java │ │ │ └── ResourceMetadataToRelativePathResourceMetadata.java │ │ ├── internal/ │ │ │ ├── BaseBlobStore.java │ │ │ ├── BlobRuntimeException.java │ │ │ ├── BlobStoreContextImpl.java │ │ │ └── RequestSigningUnsupported.java │ │ ├── options/ │ │ │ ├── CopyOptions.java │ │ │ ├── CreateContainerOptions.java │ │ │ ├── GetOptions.java │ │ │ ├── ListAllOptions.java │ │ │ ├── ListContainerOptions.java │ │ │ ├── ListOptions.java │ │ │ └── PutOptions.java │ │ ├── reference/ │ │ │ ├── BlobStoreConstants.java │ │ │ └── package-info.java │ │ ├── strategy/ │ │ │ ├── ClearContainerStrategy.java │ │ │ ├── ClearListStrategy.java │ │ │ ├── CountListStrategy.java │ │ │ ├── DeleteDirectoryStrategy.java │ │ │ ├── GetBlobsInListStrategy.java │ │ │ ├── GetDirectoryStrategy.java │ │ │ ├── ListBlobsInContainer.java │ │ │ ├── ListContainerStrategy.java │ │ │ ├── MkdirStrategy.java │ │ │ ├── PutBlobsStrategy.java │ │ │ └── internal/ │ │ │ ├── ConcatenateContainerLists.java │ │ │ ├── CountBlobTypeInList.java │ │ │ ├── DeleteAllKeysInList.java │ │ │ ├── FetchBlobMetadata.java │ │ │ ├── GetAllBlobsInListAndRetryOnFailure.java │ │ │ ├── ListContainerAndRecurseThroughFolders.java │ │ │ ├── MarkerFileMkdirStrategy.java │ │ │ ├── MarkersDeleteDirectoryStrategy.java │ │ │ ├── MarkersGetDirectoryStrategy.java │ │ │ ├── MultipartUploadSlicingAlgorithm.java │ │ │ └── PutBlobsStrategyImpl.java │ │ └── util/ │ │ ├── BlobStoreUtils.java │ │ ├── BlobUtils.java │ │ ├── ForwardingBlobStore.java │ │ ├── ReadOnlyBlobStore.java │ │ └── internal/ │ │ └── BlobUtilsImpl.java │ └── test/ │ └── java/ │ └── org/ │ └── jclouds/ │ └── blobstore/ │ ├── BlobStoreContextFactoryTest.java │ ├── BlobStoresTest.java │ ├── TransientApiMetadataTest.java │ ├── TransientBlobRequestSignerTest.java │ ├── binders/ │ │ ├── BindBlobToMultipartFormTest.java │ │ ├── BindMapToHeadersWithPrefixTest.java │ │ └── BindUserMetadataToHeadersWithPrefixTest.java │ ├── functions/ │ │ ├── BlobNameTest.java │ │ ├── BlobToHttpGetOptionsTest.java │ │ ├── ParseBlobFromHeadersAndHttpContentTest.java │ │ ├── ParseSystemAndUserMetadataFromHeadersTest.java │ │ ├── PrefixToResourceMetadataTest.java │ │ └── ResourceMetadataToRelativePathResourceMetadataTest.java │ ├── integration/ │ │ ├── TransientBlobIntegrationTest.java │ │ ├── TransientContainerIntegrationTest.java │ │ ├── TransientServiceIntegrationTest.java │ │ └── internal/ │ │ ├── BaseBlobIntegrationTest.java │ │ ├── BaseBlobLiveTest.java │ │ ├── BaseBlobSignerLiveTest.java │ │ ├── BaseBlobStoreIntegrationTest.java │ │ ├── BaseContainerIntegrationTest.java │ │ ├── BaseContainerLiveTest.java │ │ └── BaseServiceIntegrationTest.java │ ├── internal/ │ │ ├── BaseBlobSignerExpectTest.java │ │ └── BaseBlobStoreApiMetadataTest.java │ ├── options/ │ │ ├── GetOptionsTest.java │ │ └── ListOptionsTest.java │ ├── strategy/ │ │ └── internal/ │ │ ├── BiggerThanPageSizeTest.java │ │ ├── ConcatenateContainerListsTest.java │ │ ├── DeleteAllKeysInListTest.java │ │ ├── DelimiterTest.java │ │ ├── FetchBlobMetadataTest.java │ │ ├── ListContainerTest.java │ │ └── MpuPartitioningAlgorithmTest.java │ └── util/ │ └── BlobStoreUtilsTest.java ├── common/ │ ├── googlecloud/ │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── googlecloud/ │ │ │ ├── GoogleCredentialsFromJson.java │ │ │ ├── config/ │ │ │ │ ├── CurrentProject.java │ │ │ │ ├── GoogleCloudProperties.java │ │ │ │ └── ListPageAdapterFactory.java │ │ │ ├── domain/ │ │ │ │ ├── ForwardingListPage.java │ │ │ │ └── ListPage.java │ │ │ ├── internal/ │ │ │ │ ├── AdvancingIterator.java │ │ │ │ ├── BaseArg0ToIteratorOfListPage.java │ │ │ │ ├── BaseCallerArg0ToIteratorOfListPage.java │ │ │ │ ├── BaseToIteratorOfListPage.java │ │ │ │ ├── ListPages.java │ │ │ │ └── NullSafeCopies.java │ │ │ └── options/ │ │ │ └── ListOptions.java │ │ └── test/ │ │ └── java/ │ │ └── org/ │ │ └── jclouds/ │ │ └── googlecloud/ │ │ ├── config/ │ │ │ └── ClientEmailTest.java │ │ └── internal/ │ │ └── TestProperties.java │ ├── openstack/ │ │ ├── README.txt │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── openstack/ │ │ │ ├── config/ │ │ │ │ └── OpenStackAuthenticationModule.java │ │ │ ├── domain/ │ │ │ │ ├── AuthenticationResponse.java │ │ │ │ ├── Link.java │ │ │ │ └── Resource.java │ │ │ ├── filters/ │ │ │ │ ├── AddTimestampQuery.java │ │ │ │ └── AuthenticateRequest.java │ │ │ ├── functions/ │ │ │ │ ├── ParseAuthenticationResponseFromHeaders.java │ │ │ │ └── URIFromAuthenticationResponseForService.java │ │ │ ├── handlers/ │ │ │ │ └── RetryOnRenew.java │ │ │ ├── internal/ │ │ │ │ ├── Authentication.java │ │ │ │ └── OpenStackAuthClient.java │ │ │ ├── keystone/ │ │ │ │ └── v1_1/ │ │ │ │ ├── AuthenticationClient.java │ │ │ │ ├── binders/ │ │ │ │ │ └── BindCredentialsToJsonPayload.java │ │ │ │ ├── config/ │ │ │ │ │ └── AuthenticationServiceModule.java │ │ │ │ ├── domain/ │ │ │ │ │ ├── Auth.java │ │ │ │ │ ├── Endpoint.java │ │ │ │ │ └── Token.java │ │ │ │ ├── functions/ │ │ │ │ │ ├── EndpointToRegion.java │ │ │ │ │ ├── EndpointToSupplierURI.java │ │ │ │ │ ├── PublicURLOrInternalIfNull.java │ │ │ │ │ └── RegionFirstPartOfDNSNameOrProvider.java │ │ │ │ ├── handlers/ │ │ │ │ │ └── RetryOnRenew.java │ │ │ │ └── suppliers/ │ │ │ │ ├── RegionIdToURIFromAuthForServiceSupplier.java │ │ │ │ └── V1DefaultRegionIdSupplier.java │ │ │ ├── options/ │ │ │ │ └── BaseListOptions.java │ │ │ ├── predicates/ │ │ │ │ └── LinkPredicates.java │ │ │ ├── reference/ │ │ │ │ ├── AuthHeaders.java │ │ │ │ └── package-info.java │ │ │ └── services/ │ │ │ ├── Compute.java │ │ │ ├── Extension.java │ │ │ ├── Image.java │ │ │ ├── ObjectStore.java │ │ │ └── ServiceType.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── openstack/ │ │ │ ├── filters/ │ │ │ │ └── AddTimestampQueryTest.java │ │ │ ├── functions/ │ │ │ │ └── ParseAuthenticationResponseFromHeadersTest.java │ │ │ ├── handlers/ │ │ │ │ └── RetryOnRenewTest.java │ │ │ ├── internal/ │ │ │ │ ├── OpenStackAuthClientTest.java │ │ │ │ └── TestOpenStackAuthenticationModule.java │ │ │ ├── keystone/ │ │ │ │ └── v1_1/ │ │ │ │ ├── functions/ │ │ │ │ │ ├── PublicURLOrInternalIfNullTest.java │ │ │ │ │ └── RegionFirstPartOfDNSNameOrProviderTest.java │ │ │ │ ├── handlers/ │ │ │ │ │ └── RetryOnRenewTest.java │ │ │ │ ├── internal/ │ │ │ │ │ └── BaseKeystoneRestClientExpectTest.java │ │ │ │ ├── parse/ │ │ │ │ │ └── ParseAuthTest.java │ │ │ │ └── suppliers/ │ │ │ │ ├── RegionIdToURIFromAuthForServiceSupplierTest.java │ │ │ │ └── V1DefaultRegionIdSupplierTest.java │ │ │ ├── options/ │ │ │ │ └── BaseListOptionsTest.java │ │ │ └── predicates/ │ │ │ └── LinkPredicatesTest.java │ │ └── resources/ │ │ └── auth1_1.json │ └── pom.xml ├── compute/ │ ├── bnd.bnd │ ├── pom.xml │ └── src/ │ ├── main/ │ │ └── java/ │ │ └── org/ │ │ └── jclouds/ │ │ ├── cim/ │ │ │ ├── CIMPredicates.java │ │ │ ├── ManagedElement.java │ │ │ ├── OSType.java │ │ │ ├── ResourceAllocationSettingData.java │ │ │ ├── SettingData.java │ │ │ ├── VirtualSystemSettingData.java │ │ │ ├── functions/ │ │ │ │ └── HardwareBuilderFromResourceAllocations.java │ │ │ └── xml/ │ │ │ ├── ResourceAllocationSettingDataHandler.java │ │ │ └── VirtualSystemSettingDataHandler.java │ │ ├── compute/ │ │ │ ├── ComputeService.java │ │ │ ├── ComputeServiceAdapter.java │ │ │ ├── ComputeServiceContext.java │ │ │ ├── JCloudsNativeComputeServiceAdapter.java │ │ │ ├── RunNodesException.java │ │ │ ├── RunScriptOnNodesException.java │ │ │ ├── Utils.java │ │ │ ├── callables/ │ │ │ │ ├── BlockUntilInitScriptStatusIsZeroThenReturnOutput.java │ │ │ │ ├── InitScriptConfigurationForTasks.java │ │ │ │ ├── RunScriptOnNode.java │ │ │ │ ├── RunScriptOnNodeAsInitScriptUsingSsh.java │ │ │ │ ├── RunScriptOnNodeAsInitScriptUsingSshAndBlockUntilComplete.java │ │ │ │ ├── RunScriptOnNodeUsingSsh.java │ │ │ │ ├── ScriptStillRunningException.java │ │ │ │ └── SudoAwareInitManager.java │ │ │ ├── config/ │ │ │ │ ├── AdminAccessConfiguration.java │ │ │ │ ├── BaseComputeServiceContextModule.java │ │ │ │ ├── BindComputeStrategiesByClass.java │ │ │ │ ├── BindComputeSuppliersByClass.java │ │ │ │ ├── ComputeServiceAdapterContextModule.java │ │ │ │ ├── ComputeServiceProperties.java │ │ │ │ ├── ComputeServiceTimeoutsModule.java │ │ │ │ ├── CustomizationResponse.java │ │ │ │ ├── GetLoginForProviderFromPropertiesAndStoreCredentialsOrReturnNull.java │ │ │ │ ├── JCloudsNativeComputeServiceAdapterContextModule.java │ │ │ │ ├── PersistNodeCredentialsModule.java │ │ │ │ └── ResolvesImages.java │ │ │ ├── domain/ │ │ │ │ ├── CIMOperatingSystem.java │ │ │ │ ├── CloneImageTemplate.java │ │ │ │ ├── ComputeMetadata.java │ │ │ │ ├── ComputeMetadataBuilder.java │ │ │ │ ├── ComputeMetadataIncludingStatus.java │ │ │ │ ├── ComputeType.java │ │ │ │ ├── ExecChannel.java │ │ │ │ ├── ExecResponse.java │ │ │ │ ├── Hardware.java │ │ │ │ ├── HardwareBuilder.java │ │ │ │ ├── Image.java │ │ │ │ ├── ImageBuilder.java │ │ │ │ ├── ImageTemplate.java │ │ │ │ ├── ImageTemplateBuilder.java │ │ │ │ ├── LoginType.java │ │ │ │ ├── NodeMetadata.java │ │ │ │ ├── NodeMetadataBuilder.java │ │ │ │ ├── OperatingSystem.java │ │ │ │ ├── OsFamily.java │ │ │ │ ├── OsFamilyVersion64Bit.java │ │ │ │ ├── Processor.java │ │ │ │ ├── SecurityGroup.java │ │ │ │ ├── SecurityGroupBuilder.java │ │ │ │ ├── Template.java │ │ │ │ ├── TemplateBuilder.java │ │ │ │ ├── TemplateBuilderSpec.java │ │ │ │ ├── Volume.java │ │ │ │ ├── VolumeBuilder.java │ │ │ │ └── internal/ │ │ │ │ ├── ArbitraryCpuRamTemplateBuilderImpl.java │ │ │ │ ├── ComputeMetadataImpl.java │ │ │ │ ├── HardwareImpl.java │ │ │ │ ├── ImageImpl.java │ │ │ │ ├── ImageTemplateImpl.java │ │ │ │ ├── NodeMetadataImpl.java │ │ │ │ ├── NullEqualToIsParentOrIsGrandparentOfCurrentLocation.java │ │ │ │ ├── TemplateBuilderImpl.java │ │ │ │ ├── TemplateImpl.java │ │ │ │ └── VolumeImpl.java │ │ │ ├── events/ │ │ │ │ ├── InitScriptOnNodeSubmission.java │ │ │ │ ├── StatementOnNode.java │ │ │ │ ├── StatementOnNodeCompletion.java │ │ │ │ ├── StatementOnNodeFailure.java │ │ │ │ └── StatementOnNodeSubmission.java │ │ │ ├── extensions/ │ │ │ │ ├── ImageExtension.java │ │ │ │ ├── SecurityGroupExtension.java │ │ │ │ └── internal/ │ │ │ │ └── DelegatingImageExtension.java │ │ │ ├── functions/ │ │ │ │ ├── CreateSshClientOncePortIsListeningOnNode.java │ │ │ │ ├── DefaultCredentialsFromImageOrOverridingCredentials.java │ │ │ │ ├── GroupNamingConvention.java │ │ │ │ ├── InstallKeysAndRunScript.java │ │ │ │ ├── NodeAndTemplateOptionsToStatement.java │ │ │ │ ├── NodeAndTemplateOptionsToStatementWithoutPublicKey.java │ │ │ │ ├── PollNodeRunning.java │ │ │ │ └── Sha512Crypt.java │ │ │ ├── internal/ │ │ │ │ ├── BaseComputeService.java │ │ │ │ ├── ComputeServiceContextImpl.java │ │ │ │ ├── FormatSharedNamesAndAppendUniqueStringToThoseWhichRepeat.java │ │ │ │ ├── PersistNodeCredentials.java │ │ │ │ └── UtilsImpl.java │ │ │ ├── options/ │ │ │ │ ├── RunScriptOptions.java │ │ │ │ └── TemplateOptions.java │ │ │ ├── predicates/ │ │ │ │ ├── AtomicImageAvailable.java │ │ │ │ ├── AtomicImageDeleted.java │ │ │ │ ├── AtomicNodeRunning.java │ │ │ │ ├── AtomicNodeSuspended.java │ │ │ │ ├── AtomicNodeTerminated.java │ │ │ │ ├── HardwarePredicates.java │ │ │ │ ├── ImagePredicates.java │ │ │ │ ├── NodePredicates.java │ │ │ │ ├── OperatingSystemPredicates.java │ │ │ │ ├── ScriptStatusReturnsZero.java │ │ │ │ └── internal/ │ │ │ │ ├── RefreshAndDoubleCheckOnFailUnlessStatusInvalid.java │ │ │ │ ├── RefreshImageAndDoubleCheckOnFailUnlessStatusInvalid.java │ │ │ │ ├── RefreshNodeAndDoubleCheckOnFailUnlessStatusInvalid.java │ │ │ │ └── TrueIfNullOrDeletedRefreshAndDoubleCheckOnFalse.java │ │ │ ├── reference/ │ │ │ │ └── ComputeServiceConstants.java │ │ │ ├── strategy/ │ │ │ │ ├── CreateNodeWithGroupEncodedIntoName.java │ │ │ │ ├── CreateNodesInGroupThenAddToSet.java │ │ │ │ ├── CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.java │ │ │ │ ├── DestroyNodeStrategy.java │ │ │ │ ├── GetImageStrategy.java │ │ │ │ ├── GetNodeMetadataStrategy.java │ │ │ │ ├── InitializeRunScriptOnNodeOrPlaceInBadMap.java │ │ │ │ ├── ListNodesStrategy.java │ │ │ │ ├── PopulateDefaultLoginCredentialsForImageStrategy.java │ │ │ │ ├── PrioritizeCredentialsFromTemplate.java │ │ │ │ ├── RebootNodeStrategy.java │ │ │ │ ├── ResumeNodeStrategy.java │ │ │ │ ├── RunScriptOnNodeAndAddToGoodMapOrPutExceptionIntoBadMap.java │ │ │ │ ├── SuspendNodeStrategy.java │ │ │ │ └── impl/ │ │ │ │ ├── AdaptingComputeServiceStrategies.java │ │ │ │ ├── CreateNodesWithGroupEncodedIntoNameThenAddToSet.java │ │ │ │ └── ReturnCredentialsBoundToImage.java │ │ │ ├── stub/ │ │ │ │ ├── StubApiMetadata.java │ │ │ │ ├── config/ │ │ │ │ │ ├── StubComputeServiceAdapter.java │ │ │ │ │ ├── StubComputeServiceContextModule.java │ │ │ │ │ └── StubComputeServiceDependenciesModule.java │ │ │ │ └── extensions/ │ │ │ │ └── StubSecurityGroupExtension.java │ │ │ ├── suppliers/ │ │ │ │ └── ImageCacheSupplier.java │ │ │ └── util/ │ │ │ ├── AutomaticHardwareIdSpec.java │ │ │ ├── ComputeServiceUtils.java │ │ │ ├── ComputeUtils.java │ │ │ ├── ConcurrentOpenSocketFinder.java │ │ │ └── OpenSocketFinder.java │ │ ├── net/ │ │ │ ├── domain/ │ │ │ │ ├── IpPermission.java │ │ │ │ └── IpProtocol.java │ │ │ └── util/ │ │ │ └── IpPermissions.java │ │ ├── ovf/ │ │ │ ├── Configuration.java │ │ │ ├── DeploymentOptionSection.java │ │ │ ├── Disk.java │ │ │ ├── DiskSection.java │ │ │ ├── Envelope.java │ │ │ ├── Network.java │ │ │ ├── NetworkSection.java │ │ │ ├── OperatingSystemSection.java │ │ │ ├── ProductSection.java │ │ │ ├── Property.java │ │ │ ├── Section.java │ │ │ ├── VirtualHardwareSection.java │ │ │ ├── VirtualSystem.java │ │ │ ├── internal/ │ │ │ │ ├── BaseEnvelope.java │ │ │ │ └── BaseVirtualSystem.java │ │ │ └── xml/ │ │ │ ├── DeploymentOptionSectionHandler.java │ │ │ ├── DiskSectionHandler.java │ │ │ ├── EnvelopeHandler.java │ │ │ ├── NetworkSectionHandler.java │ │ │ ├── OperatingSystemSectionHandler.java │ │ │ ├── ProductSectionHandler.java │ │ │ ├── SectionHandler.java │ │ │ ├── VirtualHardwareSectionHandler.java │ │ │ ├── VirtualSystemHandler.java │ │ │ └── internal/ │ │ │ ├── BaseEnvelopeHandler.java │ │ │ └── BaseVirtualSystemHandler.java │ │ └── ssh/ │ │ ├── SshClient.java │ │ ├── SshException.java │ │ ├── SshKeyPairGenerator.java │ │ ├── SshKeys.java │ │ ├── config/ │ │ │ └── ConfiguresSshClient.java │ │ └── internal/ │ │ └── RsaSshKeyPairGenerator.java │ └── test/ │ ├── java/ │ │ └── org/ │ │ └── jclouds/ │ │ ├── compute/ │ │ │ ├── ComputeTestUtils.java │ │ │ ├── JettyStatements.java │ │ │ ├── StubComputeServiceIntegrationTest.java │ │ │ ├── StubTemplateBuilderIntegrationTest.java │ │ │ ├── callables/ │ │ │ │ ├── BlockUntilInitScriptStatusIsZeroThenReturnOutputTest.java │ │ │ │ ├── InitScriptConfigurationForTasksTest.java │ │ │ │ ├── RunScriptOnNodeAsInitScriptUsingSshAndBlockUntilCompleteTest.java │ │ │ │ ├── RunScriptOnNodeAsInitScriptUsingSshTest.java │ │ │ │ ├── RunScriptOnNodeUsingSshTest.java │ │ │ │ └── ScriptStillRunningExceptionTest.java │ │ │ ├── config/ │ │ │ │ ├── ComputeServicePropertiesTest.java │ │ │ │ ├── GetLoginForProviderFromPropertiesAndStoreCredentialsOrReturnNullTest.java │ │ │ │ └── PersistNodeCredentialsTest.java │ │ │ ├── domain/ │ │ │ │ ├── ImageBuilderTest.java │ │ │ │ ├── TemplateBuilderSpecTest.java │ │ │ │ ├── VolumeBuilderTest.java │ │ │ │ └── internal/ │ │ │ │ ├── ArbitraryCpuRamTemplateBuilderImplTest.java │ │ │ │ ├── NullEqualToIsParentOrIsGrandparentOfCurrentLocationTest.java │ │ │ │ └── TemplateBuilderImplTest.java │ │ │ ├── extensions/ │ │ │ │ └── internal/ │ │ │ │ ├── BaseImageExtensionLiveTest.java │ │ │ │ ├── BaseSecurityGroupExtensionLiveTest.java │ │ │ │ └── DelegatingImageExtensionTest.java │ │ │ ├── functions/ │ │ │ │ ├── DefaultCredentialsFromImageOrOverridingCredentialsTest.java │ │ │ │ ├── NodeAndTemplateOptionsToStatementWithoutPublicKeyTest.java │ │ │ │ ├── PollNodeRunningTest.java │ │ │ │ └── Sha512CryptTest.java │ │ │ ├── internal/ │ │ │ │ ├── BaseComputeServiceApiMetadataTest.java │ │ │ │ ├── BaseComputeServiceContextLiveTest.java │ │ │ │ ├── BaseComputeServiceLiveTest.java │ │ │ │ ├── BaseGenericComputeServiceContextLiveTest.java │ │ │ │ ├── BaseTemplateBuilderLiveTest.java │ │ │ │ └── FormatSharedNamesAndAppendUniqueStringToThoseWhichRepeatTest.java │ │ │ ├── options/ │ │ │ │ └── TemplateOptionsTest.java │ │ │ ├── predicates/ │ │ │ │ ├── AtomicNodePredicatesTest.java │ │ │ │ ├── HardwarePredicatesTest.java │ │ │ │ ├── ImagePredicatesTest.java │ │ │ │ ├── OperatingSystemPredicatesTest.java │ │ │ │ └── SocketOpenPredicates.java │ │ │ ├── strategy/ │ │ │ │ ├── CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapTest.java │ │ │ │ ├── PrioritizeCredentialsFromTemplateTest.java │ │ │ │ └── impl/ │ │ │ │ └── ReturnCredentialsBoundToImageTest.java │ │ │ ├── stub/ │ │ │ │ ├── StubApiMetadataTest.java │ │ │ │ └── extensions/ │ │ │ │ └── StubSecurityGroupExtensionIntegrationTest.java │ │ │ ├── suppliers/ │ │ │ │ └── ImageCacheSupplierTest.java │ │ │ └── util/ │ │ │ ├── AutomaticHardwareIdSpecTest.java │ │ │ ├── ComputeServiceUtilsTest.java │ │ │ └── ConcurrentOpenSocketFinderTest.java │ │ ├── net/ │ │ │ ├── domain/ │ │ │ │ └── IpPermissionTest.java │ │ │ └── util/ │ │ │ └── IpPermissionsTest.java │ │ ├── ovf/ │ │ │ └── xml/ │ │ │ ├── DiskSectionHandlerTest.java │ │ │ ├── NetworkSectionHandlerTest.java │ │ │ ├── OperatingSystemSectionHandlerTest.java │ │ │ └── ProductSectionHandlerTest.java │ │ └── ssh/ │ │ ├── SshKeysTest.java │ │ └── config/ │ │ └── RsaSshKeyPairGeneratorTest.java │ └── resources/ │ ├── .gitattributes │ ├── disksection.xml │ ├── initscript_with_java.sh │ ├── initscript_with_jetty.sh │ ├── log4j.xml │ ├── logback.xml │ ├── networksection.xml │ ├── operatingsystemsection.xml │ ├── productsection.xml │ ├── resourceallocation.xml │ ├── runscript.sh │ └── runscript_adminUpdate.sh ├── core/ │ ├── bnd.bnd │ ├── pom.xml │ └── src/ │ ├── main/ │ │ └── java/ │ │ └── org/ │ │ └── jclouds/ │ │ ├── Constants.java │ │ ├── Context.java │ │ ├── ContextBuilder.java │ │ ├── Fallback.java │ │ ├── Fallbacks.java │ │ ├── JcloudsVersion.java │ │ ├── View.java │ │ ├── annotations/ │ │ │ └── Name.java │ │ ├── apis/ │ │ │ ├── ApiMetadata.java │ │ │ ├── ApiPredicates.java │ │ │ ├── Apis.java │ │ │ └── internal/ │ │ │ └── BaseApiMetadata.java │ │ ├── collect/ │ │ │ ├── AbstractMapEntry.java │ │ │ ├── AdvanceUntilEmptyIterable.java │ │ │ ├── IterableWithMarker.java │ │ │ ├── IterableWithMarkers.java │ │ │ ├── Memoized.java │ │ │ ├── PagedIterable.java │ │ │ ├── PagedIterables.java │ │ │ ├── TransformingMap.java │ │ │ └── internal/ │ │ │ ├── Arg0ToPagedIterable.java │ │ │ ├── ArgsToPagedIterable.java │ │ │ └── CallerArg0ToPagedIterable.java │ │ ├── concurrent/ │ │ │ ├── DynamicExecutors.java │ │ │ ├── DynamicThreadPoolExecutor.java │ │ │ ├── FutureIterables.java │ │ │ ├── SingleThreaded.java │ │ │ ├── TransformParallelException.java │ │ │ └── config/ │ │ │ ├── ConfiguresExecutorService.java │ │ │ ├── ExecutorServiceModule.java │ │ │ ├── ScheduledExecutorServiceModule.java │ │ │ └── WithSubmissionTrace.java │ │ ├── config/ │ │ │ ├── BindApiContextWithWildcardExtendsExplicitAndRawType.java │ │ │ ├── BindNameToContext.java │ │ │ ├── ContextLinking.java │ │ │ └── ValueOfConfigurationKeyOrNull.java │ │ ├── crypto/ │ │ │ ├── ASN1Codec.java │ │ │ ├── Crypto.java │ │ │ ├── Macs.java │ │ │ └── Pems.java │ │ ├── date/ │ │ │ ├── DateCodec.java │ │ │ ├── DateCodecFactory.java │ │ │ ├── DateService.java │ │ │ ├── TimeStamp.java │ │ │ └── internal/ │ │ │ ├── DateServiceDateCodecFactory.java │ │ │ ├── DateUtils.java │ │ │ └── SimpleDateFormatDateService.java │ │ ├── domain/ │ │ │ ├── Credentials.java │ │ │ ├── JsonBall.java │ │ │ ├── Location.java │ │ │ ├── LocationBuilder.java │ │ │ ├── LocationScope.java │ │ │ ├── LoginCredentials.java │ │ │ ├── MutableResourceMetadata.java │ │ │ ├── ResourceMetadata.java │ │ │ ├── ResourceMetadataBuilder.java │ │ │ └── internal/ │ │ │ ├── LocationImpl.java │ │ │ ├── MutableResourceMetadataImpl.java │ │ │ └── ResourceMetadataImpl.java │ │ ├── encryption/ │ │ │ └── internal/ │ │ │ └── JCECrypto.java │ │ ├── events/ │ │ │ ├── config/ │ │ │ │ ├── ConfiguresEventBus.java │ │ │ │ ├── EventBusModule.java │ │ │ │ └── annotations/ │ │ │ │ └── AsyncBus.java │ │ │ └── handlers/ │ │ │ └── DeadEventLoggingHandler.java │ │ ├── fallbacks/ │ │ │ ├── HeaderToRetryAfterException.java │ │ │ ├── MapHttp4xxCodesToExceptions.java │ │ │ └── PropagateIfRetryAfter.java │ │ ├── functions/ │ │ │ ├── ExpandProperties.java │ │ │ ├── IdentityFunction.java │ │ │ ├── JoinOnComma.java │ │ │ ├── OnlyElementOrNull.java │ │ │ └── ToLowerCase.java │ │ ├── http/ │ │ │ ├── HttpCommand.java │ │ │ ├── HttpCommandExecutorService.java │ │ │ ├── HttpErrorHandler.java │ │ │ ├── HttpException.java │ │ │ ├── HttpMessage.java │ │ │ ├── HttpRequest.java │ │ │ ├── HttpRequestFilter.java │ │ │ ├── HttpResponse.java │ │ │ ├── HttpResponseException.java │ │ │ ├── HttpRetryHandler.java │ │ │ ├── HttpUtils.java │ │ │ ├── IOExceptionRetryHandler.java │ │ │ ├── UriTemplates.java │ │ │ ├── Uris.java │ │ │ ├── annotation/ │ │ │ │ ├── ClientError.java │ │ │ │ ├── Redirection.java │ │ │ │ └── ServerError.java │ │ │ ├── config/ │ │ │ │ ├── ConfiguresHttpCommandExecutorService.java │ │ │ │ ├── JavaUrlHttpCommandExecutorServiceModule.java │ │ │ │ └── SSLModule.java │ │ │ ├── filters/ │ │ │ │ ├── BasicAuthentication.java │ │ │ │ ├── ConnectionCloseHeader.java │ │ │ │ └── StripExpectHeader.java │ │ │ ├── functions/ │ │ │ │ ├── ParseETagHeader.java │ │ │ │ ├── ParseFirstJsonValueNamed.java │ │ │ │ ├── ParseJson.java │ │ │ │ ├── ParseSax.java │ │ │ │ ├── ParseURIFromListOrLocationHeaderIf20x.java │ │ │ │ ├── ParseXMLWithJAXB.java │ │ │ │ ├── ReleasePayloadAndReturn.java │ │ │ │ ├── ReturnInputStream.java │ │ │ │ ├── ReturnStringIf2xx.java │ │ │ │ ├── ReturnTrueIf201.java │ │ │ │ ├── ReturnTrueIf2xx.java │ │ │ │ ├── UnwrapOnlyJsonValue.java │ │ │ │ ├── UnwrapOnlyJsonValueInSet.java │ │ │ │ └── config/ │ │ │ │ └── SaxParserModule.java │ │ │ ├── handlers/ │ │ │ │ ├── BackoffLimitedRetryHandler.java │ │ │ │ ├── CloseContentAndSetExceptionErrorHandler.java │ │ │ │ ├── DelegatingErrorHandler.java │ │ │ │ ├── DelegatingRetryHandler.java │ │ │ │ ├── RateLimitRetryHandler.java │ │ │ │ └── RedirectionRetryHandler.java │ │ │ ├── internal/ │ │ │ │ ├── BaseHttpCommandExecutorService.java │ │ │ │ ├── HttpWire.java │ │ │ │ ├── JavaUrlHttpCommandExecutorService.java │ │ │ │ ├── PayloadEnclosingImpl.java │ │ │ │ └── SignatureWire.java │ │ │ ├── options/ │ │ │ │ ├── BaseHttpRequestOptions.java │ │ │ │ ├── GetOptions.java │ │ │ │ └── HttpRequestOptions.java │ │ │ └── utils/ │ │ │ ├── Queries.java │ │ │ └── QueryValue.java │ │ ├── internal/ │ │ │ ├── BaseView.java │ │ │ ├── ContextImpl.java │ │ │ └── FilterStringsBoundToInjectorByName.java │ │ ├── io/ │ │ │ ├── ByteSources.java │ │ │ ├── ByteStreams2.java │ │ │ ├── ContentMetadata.java │ │ │ ├── ContentMetadataBuilder.java │ │ │ ├── ContentMetadataCodec.java │ │ │ ├── MutableContentMetadata.java │ │ │ ├── Payload.java │ │ │ ├── PayloadEnclosing.java │ │ │ ├── PayloadSlicer.java │ │ │ ├── Payloads.java │ │ │ ├── internal/ │ │ │ │ └── BasePayloadSlicer.java │ │ │ └── payloads/ │ │ │ ├── BaseCipherPayload.java │ │ │ ├── BaseImmutableContentMetadata.java │ │ │ ├── BaseMutableContentMetadata.java │ │ │ ├── BasePayload.java │ │ │ ├── ByteArrayPayload.java │ │ │ ├── ByteSourcePayload.java │ │ │ ├── DelegatingPayload.java │ │ │ ├── FilePayload.java │ │ │ ├── InputStreamPayload.java │ │ │ ├── MultipartForm.java │ │ │ ├── Part.java │ │ │ ├── PhantomPayload.java │ │ │ ├── RSADecryptingPayload.java │ │ │ ├── RSAEncryptingPayload.java │ │ │ ├── StringPayload.java │ │ │ └── UrlEncodedFormPayload.java │ │ ├── javax/ │ │ │ └── annotation/ │ │ │ ├── Nullable.java │ │ │ └── concurrent/ │ │ │ └── NotThreadSafe.java │ │ ├── json/ │ │ │ ├── Json.java │ │ │ ├── SerializedNames.java │ │ │ ├── config/ │ │ │ │ └── GsonModule.java │ │ │ └── internal/ │ │ │ ├── DeserializationConstructorAndReflectiveTypeAdapterFactory.java │ │ │ ├── EnumTypeAdapterThatReturnsFromValue.java │ │ │ ├── GsonWrapper.java │ │ │ ├── NamingStrategies.java │ │ │ ├── NullFilteringTypeAdapterFactories.java │ │ │ ├── NullHackJsonLiteralAdapter.java │ │ │ └── OptionalTypeAdapterFactory.java │ │ ├── lifecycle/ │ │ │ ├── BaseLifeCycle.java │ │ │ ├── Closer.java │ │ │ ├── LifeCycle.java │ │ │ └── config/ │ │ │ └── LifeCycleModule.java │ │ ├── location/ │ │ │ ├── Iso3166.java │ │ │ ├── Provider.java │ │ │ ├── Region.java │ │ │ ├── Zone.java │ │ │ ├── config/ │ │ │ │ └── LocationModule.java │ │ │ ├── functions/ │ │ │ │ ├── RegionToEndpoint.java │ │ │ │ ├── RegionToEndpointOrProviderIfNull.java │ │ │ │ ├── ToIdAndScope.java │ │ │ │ └── ZoneToEndpoint.java │ │ │ ├── predicates/ │ │ │ │ ├── LocationPredicates.java │ │ │ │ ├── RegionIdFilter.java │ │ │ │ ├── ZoneIdFilter.java │ │ │ │ └── fromconfig/ │ │ │ │ ├── AnyOrConfiguredRegionId.java │ │ │ │ └── AnyOrConfiguredZoneId.java │ │ │ ├── reference/ │ │ │ │ └── LocationConstants.java │ │ │ └── suppliers/ │ │ │ ├── ImplicitLocationSupplier.java │ │ │ ├── ImplicitRegionIdSupplier.java │ │ │ ├── LocationIdToIso3166CodesSupplier.java │ │ │ ├── LocationsSupplier.java │ │ │ ├── ProviderURISupplier.java │ │ │ ├── RegionIdToURISupplier.java │ │ │ ├── RegionIdToZoneIdsSupplier.java │ │ │ ├── RegionIdsSupplier.java │ │ │ ├── ZoneIdToURISupplier.java │ │ │ ├── ZoneIdsSupplier.java │ │ │ ├── all/ │ │ │ │ ├── JustProvider.java │ │ │ │ ├── RegionToProvider.java │ │ │ │ ├── RegionToProviderOrJustProvider.java │ │ │ │ ├── ZoneToProvider.java │ │ │ │ └── ZoneToRegionToProviderOrJustProvider.java │ │ │ ├── derived/ │ │ │ │ ├── RegionIdsFromRegionIdToURIKeySet.java │ │ │ │ ├── ZoneIdToURIFromJoinOnRegionIdToURI.java │ │ │ │ ├── ZoneIdsFromRegionIdToZoneIdsValues.java │ │ │ │ └── ZoneIdsFromZoneIdToURIKeySet.java │ │ │ ├── fromconfig/ │ │ │ │ ├── LocationIdToIso3166CodesFromConfiguration.java │ │ │ │ ├── LocationIdToURIFromConfigurationOrDefaultToProvider.java │ │ │ │ ├── ProviderURIFromProviderMetadata.java │ │ │ │ ├── RegionIdToURIFromConfigurationOrDefaultToProvider.java │ │ │ │ ├── RegionIdToZoneIdsFromConfiguration.java │ │ │ │ ├── RegionIdsFromConfiguration.java │ │ │ │ ├── SplitConfigurationKey.java │ │ │ │ ├── ZoneIdToURIFromConfigurationOrDefaultToProvider.java │ │ │ │ └── ZoneIdsFromConfiguration.java │ │ │ └── implicit/ │ │ │ ├── FirstNetwork.java │ │ │ ├── FirstRegion.java │ │ │ ├── FirstZone.java │ │ │ ├── GetRegionIdMatchingProviderURIOrNull.java │ │ │ ├── OnlyLocationOrFirstRegionOptionallyMatchingRegionId.java │ │ │ └── OnlyLocationOrFirstZone.java │ │ ├── logging/ │ │ │ ├── BaseLogger.java │ │ │ ├── ConsoleLogger.java │ │ │ ├── Logger.java │ │ │ ├── LoggingModules.java │ │ │ ├── NullLogger.java │ │ │ ├── config/ │ │ │ │ ├── BindLoggersAnnotatedWithResource.java │ │ │ │ ├── ConsoleLoggingModule.java │ │ │ │ ├── LoggingModule.java │ │ │ │ └── NullLoggingModule.java │ │ │ ├── internal/ │ │ │ │ └── Wire.java │ │ │ └── jdk/ │ │ │ ├── JDKLogger.java │ │ │ └── config/ │ │ │ └── JDKLoggingModule.java │ │ ├── osgi/ │ │ │ ├── Activator.java │ │ │ ├── ApiListener.java │ │ │ ├── ApiRegistry.java │ │ │ ├── Bundles.java │ │ │ ├── MetadataBundleListener.java │ │ │ ├── ProviderListener.java │ │ │ └── ProviderRegistry.java │ │ ├── predicates/ │ │ │ ├── InetSocketAddressConnect.java │ │ │ ├── SocketOpen.java │ │ │ ├── SocketOpenUnsupported.java │ │ │ ├── Validator.java │ │ │ └── validators/ │ │ │ ├── AllLowerCaseValidator.java │ │ │ └── DnsNameValidator.java │ │ ├── providers/ │ │ │ ├── AnonymousProviderMetadata.java │ │ │ ├── ProviderMetadata.java │ │ │ ├── ProviderPredicates.java │ │ │ ├── Providers.java │ │ │ ├── config/ │ │ │ │ └── BindProviderMetadataContextAndCredentials.java │ │ │ └── internal/ │ │ │ ├── BaseProviderMetadata.java │ │ │ └── UpdateProviderMetadataFromProperties.java │ │ ├── proxy/ │ │ │ ├── ProxyConfig.java │ │ │ ├── ProxyForURI.java │ │ │ └── internal/ │ │ │ └── GuiceProxyConfig.java │ │ ├── reflect/ │ │ │ ├── FunctionalReflection.java │ │ │ ├── Invocation.java │ │ │ ├── InvocationSuccess.java │ │ │ ├── Reflection2.java │ │ │ └── Types2.java │ │ ├── rest/ │ │ │ ├── AnonymousHttpApiMetadata.java │ │ │ ├── ApiContext.java │ │ │ ├── AuthorizationException.java │ │ │ ├── Binder.java │ │ │ ├── ConfiguresCredentialStore.java │ │ │ ├── ConfiguresHttpApi.java │ │ │ ├── HttpApiMetadata.java │ │ │ ├── HttpClient.java │ │ │ ├── InputParamValidator.java │ │ │ ├── InsufficientResourcesException.java │ │ │ ├── InvocationContext.java │ │ │ ├── MapBinder.java │ │ │ ├── RateLimitExceededException.java │ │ │ ├── RequestSigner.java │ │ │ ├── ResourceAlreadyExistsException.java │ │ │ ├── ResourceNotFoundException.java │ │ │ ├── RetryAfterException.java │ │ │ ├── Utils.java │ │ │ ├── annotations/ │ │ │ │ ├── Api.java │ │ │ │ ├── ApiVersion.java │ │ │ │ ├── ApiVersionOverride.java │ │ │ │ ├── BinderParam.java │ │ │ │ ├── BuildVersion.java │ │ │ │ ├── Delegate.java │ │ │ │ ├── Endpoint.java │ │ │ │ ├── EndpointParam.java │ │ │ │ ├── Fallback.java │ │ │ │ ├── FormParams.java │ │ │ │ ├── Headers.java │ │ │ │ ├── JAXBResponseParser.java │ │ │ │ ├── MapBinder.java │ │ │ │ ├── OnlyElement.java │ │ │ │ ├── OverrideRequestFilters.java │ │ │ │ ├── PATCH.java │ │ │ │ ├── ParamParser.java │ │ │ │ ├── ParamValidators.java │ │ │ │ ├── PartParam.java │ │ │ │ ├── Payload.java │ │ │ │ ├── PayloadParam.java │ │ │ │ ├── PayloadParams.java │ │ │ │ ├── QueryParams.java │ │ │ │ ├── RequestFilters.java │ │ │ │ ├── ResponseParser.java │ │ │ │ ├── SelectJson.java │ │ │ │ ├── SinceApiVersion.java │ │ │ │ ├── SkipEncoding.java │ │ │ │ ├── Transform.java │ │ │ │ ├── Unwrap.java │ │ │ │ ├── VirtualHost.java │ │ │ │ ├── WrapWith.java │ │ │ │ └── XMLResponseParser.java │ │ │ ├── binders/ │ │ │ │ ├── BindAsHostPrefix.java │ │ │ │ ├── BindException.java │ │ │ │ ├── BindMapToStringPayload.java │ │ │ │ ├── BindToJsonPayload.java │ │ │ │ ├── BindToJsonPayloadWrappedWith.java │ │ │ │ ├── BindToStringPayload.java │ │ │ │ └── BindToXMLPayload.java │ │ │ ├── config/ │ │ │ │ ├── AnnotatedHttpApiProvider.java │ │ │ │ ├── BinderUtils.java │ │ │ │ ├── CredentialStoreModule.java │ │ │ │ ├── HttpApiModule.java │ │ │ │ ├── InvocationConfig.java │ │ │ │ ├── ReadAnnotationsAndProperties.java │ │ │ │ ├── RestModule.java │ │ │ │ └── SetCaller.java │ │ │ ├── functions/ │ │ │ │ ├── AlwaysPresentImplicitOptionalConverter.java │ │ │ │ ├── ImplicitOptionalConverter.java │ │ │ │ └── PresentWhenApiVersionLexicographicallyAtOrAfterSinceApiVersion.java │ │ │ ├── internal/ │ │ │ │ ├── ApiContextImpl.java │ │ │ │ ├── BaseHttpApiMetadata.java │ │ │ │ ├── DelegatesToInvocationFunction.java │ │ │ │ ├── GeneratedHttpRequest.java │ │ │ │ ├── GetAcceptHeaders.java │ │ │ │ ├── InvokeHttpMethod.java │ │ │ │ ├── RestAnnotationProcessor.java │ │ │ │ ├── TransformerForRequest.java │ │ │ │ └── UtilsImpl.java │ │ │ └── suppliers/ │ │ │ ├── MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.java │ │ │ ├── SetAndThrowAuthorizationExceptionSupplier.java │ │ │ ├── URIFromStringSupplier.java │ │ │ └── ValueLoadedCallback.java │ │ ├── suppliers/ │ │ │ └── SupplyKeyMatchingValueOrNull.java │ │ ├── util/ │ │ │ ├── Closeables2.java │ │ │ ├── InetAddresses2.java │ │ │ ├── Maps2.java │ │ │ ├── Multimaps2.java │ │ │ ├── Optionals2.java │ │ │ ├── PasswordGenerator.java │ │ │ ├── Patterns.java │ │ │ ├── Predicates2.java │ │ │ ├── SaxUtils.java │ │ │ ├── Strings2.java │ │ │ ├── Suppliers2.java │ │ │ ├── Throwables2.java │ │ │ └── TypeTokenUtils.java │ │ └── xml/ │ │ ├── XMLParser.java │ │ └── internal/ │ │ └── JAXBParser.java │ └── test/ │ ├── java/ │ │ └── org/ │ │ └── jclouds/ │ │ ├── ContextBuilderTest.java │ │ ├── JcloudsVersionTest.java │ │ ├── PerformanceTest.java │ │ ├── apis/ │ │ │ ├── ApisTest.java │ │ │ ├── Balancer.java │ │ │ ├── BaseApiLiveTest.java │ │ │ ├── BaseContextLiveTest.java │ │ │ ├── BaseViewLiveTest.java │ │ │ ├── Compute.java │ │ │ ├── JcloudsTestBlobStoreApiMetadata.java │ │ │ ├── JcloudsTestComputeApiMetadata.java │ │ │ ├── JcloudsTestYetAnotherComputeApiMetadata.java │ │ │ ├── Storage.java │ │ │ └── internal/ │ │ │ └── BaseApiMetadataTest.java │ │ ├── collect/ │ │ │ ├── AdvanceUntilEmptyIterableTest.java │ │ │ ├── IterableWithMarkersTest.java │ │ │ ├── PagedIterablesTest.java │ │ │ └── internal/ │ │ │ ├── Arg0ToPagedIterableTest.java │ │ │ └── ArgsToPagedIterableTest.java │ │ ├── concurrent/ │ │ │ ├── DynamicThreadPoolExecutorTest.java │ │ │ ├── FutureIterablesTest.java │ │ │ └── config/ │ │ │ ├── ExecutorServiceModuleTest.java │ │ │ └── ScheduledExecutorServiceModuleTest.java │ │ ├── config/ │ │ │ ├── ContextLinkingTest.java │ │ │ └── ValueOfConfigurationKeyOrNullTest.java │ │ ├── crypto/ │ │ │ └── PemsTest.java │ │ ├── date/ │ │ │ ├── DateServiceTest.java │ │ │ └── internal/ │ │ │ ├── DateServiceDateCodecFactoryTest.java │ │ │ ├── DateUtilsTest.java │ │ │ └── SimpleDateFormatDateServiceTest.java │ │ ├── domain/ │ │ │ ├── CredentialsTest.java │ │ │ ├── JsonBallTest.java │ │ │ ├── JsonObjectTest.java │ │ │ └── LoginCredentialsTest.java │ │ ├── events/ │ │ │ └── config/ │ │ │ └── EventBusModuleTest.java │ │ ├── fallbacks/ │ │ │ ├── HeaderToRetryAfterExceptionTest.java │ │ │ └── MapHttp4xxCodesToExceptionsTest.java │ │ ├── functions/ │ │ │ ├── CacheLearningTest.java │ │ │ ├── ExpandPropertiesTest.java │ │ │ └── JoinOnCommaTest.java │ │ ├── http/ │ │ │ ├── BackoffLimitedRetryJavaTest.java │ │ │ ├── BaseHttpCommandExecutorServiceIntegrationTest.java │ │ │ ├── BaseHttpErrorHandlerTest.java │ │ │ ├── BaseMockWebServerTest.java │ │ │ ├── HttpMessageTest.java │ │ │ ├── HttpRequestTest.java │ │ │ ├── IntegrationTestClient.java │ │ │ ├── IntegrationTestClientExpectTest.java │ │ │ ├── JavaUrlHttpCommandExecutorServiceIntegrationTest.java │ │ │ ├── TransformingHttpCommandImplTest.java │ │ │ ├── UriTemplatesTest.java │ │ │ ├── UrisTest.java │ │ │ ├── config/ │ │ │ │ └── SSLModuleTest.java │ │ │ ├── filters/ │ │ │ │ ├── BasicAuthenticationTest.java │ │ │ │ ├── ConnectionCloseHeaderTest.java │ │ │ │ └── StripExpectHeaderTest.java │ │ │ ├── functions/ │ │ │ │ ├── BaseHandlerTest.java │ │ │ │ ├── ParseFirstJsonValueNamedTest.java │ │ │ │ ├── ParseSaxTest.java │ │ │ │ ├── ParseURIFromListOrLocationHeaderIf20xTest.java │ │ │ │ ├── ReturnStringIf200Test.java │ │ │ │ └── UnwrapFirstValueNamedTest.java │ │ │ ├── handlers/ │ │ │ │ ├── BackoffLimitedRetryHandlerTest.java │ │ │ │ ├── BaseHttpErrorHandlerTest.java │ │ │ │ ├── DelegatingErrorHandlerTest.java │ │ │ │ ├── RateLimitRetryHandlerTest.java │ │ │ │ └── RedirectionRetryHandlerTest.java │ │ │ ├── internal/ │ │ │ │ ├── BaseHttpCommandExecutorServiceTest.java │ │ │ │ ├── TrackingJavaUrlHttpCommandExecutorService.java │ │ │ │ ├── WireLiveTest.java │ │ │ │ └── WireTest.java │ │ │ ├── options/ │ │ │ │ └── GetOptionsTest.java │ │ │ └── utils/ │ │ │ └── QueriesTest.java │ │ ├── internal/ │ │ │ ├── BaseViewTest.java │ │ │ └── FilterStringsBoundToInjectorByNameTest.java │ │ ├── io/ │ │ │ ├── DefaultContentMetadataCodecTest.java │ │ │ ├── internal/ │ │ │ │ └── BasePayloadSlicerTest.java │ │ │ └── payloads/ │ │ │ ├── MultipartFormTest.java │ │ │ └── StringPayloadTest.java │ │ ├── json/ │ │ │ ├── BaseItemParserTest.java │ │ │ ├── BaseIterableWithMarkerParserTest.java │ │ │ ├── BaseParserTest.java │ │ │ ├── BaseSetParserTest.java │ │ │ ├── GsonExperimentsTest.java │ │ │ ├── JsonTest.java │ │ │ └── internal/ │ │ │ ├── DeserializationConstructorAndReflectiveTypeAdapterFactoryTest.java │ │ │ ├── NamingStrategiesTest.java │ │ │ ├── NullFilteringTypeAdapterFactoriesTest.java │ │ │ ├── NullHackJsonLiteralAdapterTest.java │ │ │ └── OptionalTypeAdapterFactoryTest.java │ │ ├── lifecycle/ │ │ │ └── config/ │ │ │ └── LifeCycleModuleTest.java │ │ ├── location/ │ │ │ ├── config/ │ │ │ │ └── ProvideIso3166CodesByLocationIdViaPropertiesTest.java │ │ │ ├── functions/ │ │ │ │ ├── RegionToEndpointOrProviderIfNullTest.java │ │ │ │ ├── RegionToEndpointTest.java │ │ │ │ └── ZoneToEndpointTest.java │ │ │ ├── predicates/ │ │ │ │ └── fromconfig/ │ │ │ │ ├── AnyOrConfiguredRegionIdTest.java │ │ │ │ └── AnyOrConfiguredZoneIdTest.java │ │ │ └── suppliers/ │ │ │ ├── all/ │ │ │ │ ├── JustProviderTest.java │ │ │ │ ├── RegionToProviderTest.java │ │ │ │ ├── ZoneToProviderTest.java │ │ │ │ └── ZoneToRegionToProviderOrJustProviderTest.java │ │ │ ├── derived/ │ │ │ │ └── ZoneIdToURIFromJoinOnRegionIdToURITest.java │ │ │ └── implicit/ │ │ │ ├── FirstNetworkTest.java │ │ │ ├── FirstRegionTest.java │ │ │ ├── FirstZoneTest.java │ │ │ ├── OnlyLocationOrFirstRegionOptionallyMatchingRegionIdTest.java │ │ │ └── OnlyLocationOrFirstZoneTest.java │ │ ├── logging/ │ │ │ ├── BufferLogger.java │ │ │ ├── BufferLoggerTest.java │ │ │ └── config/ │ │ │ └── BindLoggersAnnotatedWithResourceTest.java │ │ ├── osgi/ │ │ │ ├── BundlesTest.java │ │ │ └── MetadataBundleListenerTest.java │ │ ├── providers/ │ │ │ ├── JcloudsTestBlobStoreProviderMetadata.java │ │ │ ├── JcloudsTestComputeProviderMetadata.java │ │ │ ├── JcloudsTestYetAnotherComputeProviderMetadata.java │ │ │ ├── ProvidersTest.java │ │ │ ├── config/ │ │ │ │ └── BindProviderMetadataContextAndCredentialsTest.java │ │ │ └── internal/ │ │ │ ├── BaseProviderMetadataTest.java │ │ │ └── UpdateProviderMetadataFromPropertiesTest.java │ │ ├── proxy/ │ │ │ └── ProxyForURITest.java │ │ ├── reflect/ │ │ │ ├── FunctionalReflectionTest.java │ │ │ ├── Reflection2CoreJavaClassesTest.java │ │ │ ├── Reflection2OverriddenMethodTest.java │ │ │ └── Reflection2Test.java │ │ ├── rest/ │ │ │ ├── CredentialStoreModuleTest.java │ │ │ ├── InputParamValidatorTest.java │ │ │ ├── annotationparsing/ │ │ │ │ ├── ClosableApiTest.java │ │ │ │ ├── DelegateAnnotationExpectTest.java │ │ │ │ ├── JAXBResponseParserAnnotationExpectTest.java │ │ │ │ ├── PATCHAnnotationExpectTest.java │ │ │ │ └── ProvidesAnnotationExpectTest.java │ │ │ ├── binders/ │ │ │ │ ├── BindAsHostPrefixIfConfiguredTest.java │ │ │ │ ├── BindMapToStringPayloadTest.java │ │ │ │ ├── BindToJsonPayloadTest.java │ │ │ │ ├── BindToJsonPayloadWrappedWithTest.java │ │ │ │ ├── BindToStringPayloadTest.java │ │ │ │ └── BindToXMLPayloadTest.java │ │ │ ├── config/ │ │ │ │ └── ReadAnnotationsAndPropertiesTest.java │ │ │ ├── functions/ │ │ │ │ └── PresentWhenApiVersionLexicographicallyAtOrAfterSinceApiVersionTest.java │ │ │ ├── internal/ │ │ │ │ ├── BaseHttpApiMetadataTest.java │ │ │ │ ├── BaseRestAnnotationProcessingTest.java │ │ │ │ ├── BaseRestApiExpectTest.java │ │ │ │ ├── BaseRestApiTest.java │ │ │ │ ├── InvokeHttpMethodTest.java │ │ │ │ └── RestAnnotationProcessorTest.java │ │ │ └── suppliers/ │ │ │ ├── MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplierTest.java │ │ │ └── SetAndThrowAuthorizationExceptionSupplierTest.java │ │ ├── suppliers/ │ │ │ └── SupplyKeyMatchingValueOrNullTest.java │ │ ├── test/ │ │ │ └── testng/ │ │ │ └── UnitTestStatusListener.java │ │ ├── util/ │ │ │ ├── HttpUtilsTest.java │ │ │ ├── InetAddresses2Test.java │ │ │ ├── Maps2Test.java │ │ │ ├── Multimaps2Test.java │ │ │ ├── Optionals2Test.java │ │ │ ├── PasswordGeneratorTest.java │ │ │ ├── Predicates2Test.java │ │ │ ├── Strings2Test.java │ │ │ ├── Suppliers2Test.java │ │ │ └── Throwables2Test.java │ │ └── utils/ │ │ ├── TestUtils.java │ │ └── TestUtilsTest.java │ └── resources/ │ ├── META-INF/ │ │ └── maven/ │ │ └── org.apache.jclouds/ │ │ └── jclouds-core/ │ │ └── pom.properties │ ├── test │ ├── test.jks │ └── test.pub ├── drivers/ │ ├── apachehc/ │ │ ├── README.txt │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── http/ │ │ │ └── apachehc/ │ │ │ ├── ApacheHCHttpCommandExecutorService.java │ │ │ ├── ApacheHCUtils.java │ │ │ └── config/ │ │ │ └── ApacheHCHttpCommandExecutorServiceModule.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── http/ │ │ │ └── apachehc/ │ │ │ └── ApacheHCHttpCommandExecutorServiceTestDisabled.java │ │ └── resources/ │ │ └── test.jks │ ├── bouncycastle/ │ │ ├── README.txt │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── encryption/ │ │ │ └── bouncycastle/ │ │ │ ├── BouncyCastleCrypto.java │ │ │ └── config/ │ │ │ └── BouncyCastleCryptoModule.java │ │ └── test/ │ │ └── java/ │ │ └── org/ │ │ └── jclouds/ │ │ └── encryption/ │ │ └── bouncycastle/ │ │ ├── BouncyCastleCryptoTest.java │ │ └── BouncyCastlePasswordDecryptionTest.java │ ├── enterprise/ │ │ ├── README.txt │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ └── main/ │ │ └── java/ │ │ └── org/ │ │ └── jclouds/ │ │ └── enterprise/ │ │ └── config/ │ │ └── EnterpriseConfigurationModule.java │ ├── joda/ │ │ ├── README.txt │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── date/ │ │ │ └── joda/ │ │ │ ├── JodaDateService.java │ │ │ └── config/ │ │ │ └── JodaDateServiceModule.java │ │ └── test/ │ │ └── java/ │ │ └── org/ │ │ └── jclouds/ │ │ └── date/ │ │ └── joda/ │ │ └── JodaDateServiceTest.java │ ├── jsch/ │ │ ├── README.txt │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── ssh/ │ │ │ └── jsch/ │ │ │ ├── JschSshClient.java │ │ │ ├── SessionConnection.java │ │ │ └── config/ │ │ │ └── JschSshClientModule.java │ │ └── test/ │ │ └── java/ │ │ └── org/ │ │ └── jclouds/ │ │ └── ssh/ │ │ └── jsch/ │ │ ├── JschSshClientLiveTest.java │ │ ├── JschSshClientTest.java │ │ └── config/ │ │ └── JschSshClientModuleTest.java │ ├── log4j/ │ │ ├── README.txt │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── logging/ │ │ │ └── log4j/ │ │ │ ├── Log4JLogger.java │ │ │ └── config/ │ │ │ └── Log4JLoggingModule.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── logging/ │ │ │ └── log4j/ │ │ │ └── config/ │ │ │ └── Log4JLoggingModuleTest.java │ │ └── resources/ │ │ └── log4j.xml │ ├── okhttp/ │ │ ├── README.md │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── http/ │ │ │ └── okhttp/ │ │ │ ├── DelegatingSocketFactory.java │ │ │ ├── OkHttpClientSupplier.java │ │ │ ├── OkHttpCommandExecutorService.java │ │ │ └── config/ │ │ │ └── OkHttpCommandExecutorServiceModule.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── http/ │ │ │ └── okhttp/ │ │ │ └── OkHttpCommandExecutorServiceTest.java │ │ └── resources/ │ │ └── test.jks │ ├── pom.xml │ ├── slf4j/ │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── logging/ │ │ │ └── slf4j/ │ │ │ ├── SLF4JLogger.java │ │ │ └── config/ │ │ │ └── SLF4JLoggingModule.java │ │ └── test/ │ │ └── java/ │ │ └── org/ │ │ └── jclouds/ │ │ └── logging/ │ │ └── slf4j/ │ │ └── config/ │ │ └── SLF4JLoggingModuleTest.java │ └── sshj/ │ ├── bnd.bnd │ ├── pom.xml │ └── src/ │ ├── main/ │ │ └── java/ │ │ └── org/ │ │ └── jclouds/ │ │ └── sshj/ │ │ ├── SSHClientConnection.java │ │ ├── SshjSshClient.java │ │ └── config/ │ │ └── SshjSshClientModule.java │ └── test/ │ └── java/ │ └── org/ │ └── jclouds/ │ └── sshj/ │ ├── SshjSshClientLiveTest.java │ ├── SshjSshClientTest.java │ └── config/ │ └── SshjSshClientModuleTest.java ├── loadbalancer/ │ ├── bnd.bnd │ ├── pom.xml │ └── src/ │ ├── main/ │ │ └── java/ │ │ └── org/ │ │ └── jclouds/ │ │ └── loadbalancer/ │ │ ├── LoadBalancerService.java │ │ ├── LoadBalancerServiceAdapter.java │ │ ├── LoadBalancerServiceContext.java │ │ ├── config/ │ │ │ ├── BaseLoadBalancerServiceContextModule.java │ │ │ └── BindLoadBalancerStrategiesByClass.java │ │ ├── domain/ │ │ │ ├── LoadBalancerMetadata.java │ │ │ ├── LoadBalancerType.java │ │ │ └── internal/ │ │ │ └── LoadBalancerMetadataImpl.java │ │ ├── internal/ │ │ │ ├── BaseLoadBalancerService.java │ │ │ └── LoadBalancerServiceContextImpl.java │ │ ├── reference/ │ │ │ └── LoadBalancerConstants.java │ │ └── strategy/ │ │ ├── DestroyLoadBalancerStrategy.java │ │ ├── GetLoadBalancerMetadataStrategy.java │ │ ├── ListLoadBalancersStrategy.java │ │ └── LoadBalanceNodesStrategy.java │ └── test/ │ └── java/ │ └── org/ │ └── jclouds/ │ └── loadbalancer/ │ ├── BaseLoadBalancerServiceLiveTest.java │ └── internal/ │ └── BaseLoadBalancerServiceApiMetadataTest.java ├── pom.xml ├── project/ │ ├── bnd.bnd │ ├── pom.xml │ └── src/ │ └── etc/ │ └── header.txt ├── providers/ │ ├── aws-cloudwatch/ │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── aws/ │ │ │ └── cloudwatch/ │ │ │ └── AWSCloudWatchProviderMetadata.java │ │ └── test/ │ │ └── java/ │ │ └── org/ │ │ └── jclouds/ │ │ └── aws/ │ │ └── cloudwatch/ │ │ ├── AWSCloudWatchProviderTest.java │ │ └── features/ │ │ └── AWSMetricApiLiveTest.java │ ├── aws-ec2/ │ │ ├── README.txt │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── aws/ │ │ │ └── ec2/ │ │ │ ├── AWSEC2Api.java │ │ │ ├── AWSEC2ApiMetadata.java │ │ │ ├── AWSEC2ProviderMetadata.java │ │ │ ├── binders/ │ │ │ │ ├── BindInternetGatewayIdsToIndexedFormParams.java │ │ │ │ ├── BindLaunchSpecificationToFormParams.java │ │ │ │ ├── BindRouteTableIdsToIndexedFormParams.java │ │ │ │ ├── BindSpotInstanceRequestIdsToIndexedFormParams.java │ │ │ │ ├── BindTagFiltersToIndexedFormParams.java │ │ │ │ ├── BindTagsToIndexedFormParams.java │ │ │ │ └── BindVpcIdsToIndexedFormParams.java │ │ │ ├── compute/ │ │ │ │ ├── AWSEC2ComputeService.java │ │ │ │ ├── AWSEC2ComputeServiceContext.java │ │ │ │ ├── AWSEC2TemplateBuilderImpl.java │ │ │ │ ├── AWSEC2TemplateOptions.java │ │ │ │ ├── config/ │ │ │ │ │ ├── AWSEC2BindComputeSuppliersByClass.java │ │ │ │ │ ├── AWSEC2ComputeServiceContextModule.java │ │ │ │ │ ├── AWSEC2ComputeServiceDependenciesModule.java │ │ │ │ │ ├── ClusterCompute.java │ │ │ │ │ └── ImageQuery.java │ │ │ │ ├── extensions/ │ │ │ │ │ └── AWSEC2SecurityGroupExtension.java │ │ │ │ ├── functions/ │ │ │ │ │ ├── AWSEC2SecurityGroupToSecurityGroup.java │ │ │ │ │ ├── AWSRunningInstanceToNodeMetadata.java │ │ │ │ │ └── PresentSpotRequestsAndInstances.java │ │ │ │ ├── internal/ │ │ │ │ │ └── AWSEC2ComputeServiceContextImpl.java │ │ │ │ ├── loaders/ │ │ │ │ │ └── AWSEC2CreateSecurityGroupIfNeeded.java │ │ │ │ ├── strategy/ │ │ │ │ │ ├── AWSEC2CreateNodesInGroupThenAddToSet.java │ │ │ │ │ ├── AWSEC2DestroyNodeStrategy.java │ │ │ │ │ ├── AWSEC2GetNodeMetadataStrategy.java │ │ │ │ │ ├── AWSEC2IOExceptionRetryHandler.java │ │ │ │ │ ├── AWSEC2ListNodesStrategy.java │ │ │ │ │ ├── AWSEC2ReviseParsedImage.java │ │ │ │ │ └── CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.java │ │ │ │ └── suppliers/ │ │ │ │ ├── AWSEC2HardwareSupplier.java │ │ │ │ ├── AWSEC2ImageSupplier.java │ │ │ │ └── CallForImages.java │ │ │ ├── config/ │ │ │ │ └── AWSEC2HttpApiModule.java │ │ │ ├── domain/ │ │ │ │ ├── AWSRunningInstance.java │ │ │ │ ├── InternetGateway.java │ │ │ │ ├── InternetGatewayAttachment.java │ │ │ │ ├── LaunchSpecification.java │ │ │ │ ├── MonitoringState.java │ │ │ │ ├── PlacementGroup.java │ │ │ │ ├── RegionNameAndPublicKeyMaterial.java │ │ │ │ ├── Route.java │ │ │ │ ├── RouteTable.java │ │ │ │ ├── RouteTableAssociation.java │ │ │ │ ├── Spot.java │ │ │ │ ├── SpotInstanceRequest.java │ │ │ │ └── VPC.java │ │ │ ├── features/ │ │ │ │ ├── AWSAMIApi.java │ │ │ │ ├── AWSInstanceApi.java │ │ │ │ ├── AWSKeyPairApi.java │ │ │ │ ├── AWSSecurityGroupApi.java │ │ │ │ ├── AWSSubnetApi.java │ │ │ │ ├── InternetGatewayApi.java │ │ │ │ ├── MonitoringApi.java │ │ │ │ ├── PlacementGroupApi.java │ │ │ │ ├── RouteTableApi.java │ │ │ │ ├── SpotInstanceApi.java │ │ │ │ └── VPCApi.java │ │ │ ├── functions/ │ │ │ │ ├── CreatePlacementGroupIfNeeded.java │ │ │ │ ├── ImportOrReturnExistingKeypair.java │ │ │ │ └── SpotInstanceRequestToAWSRunningInstance.java │ │ │ ├── options/ │ │ │ │ ├── AWSDescribeImagesOptions.java │ │ │ │ ├── AWSRunInstancesOptions.java │ │ │ │ ├── CreateSecurityGroupOptions.java │ │ │ │ ├── CreateSubnetOptions.java │ │ │ │ ├── CreateVpcOptions.java │ │ │ │ ├── DescribeSpotPriceHistoryOptions.java │ │ │ │ ├── InternetGatewayOptions.java │ │ │ │ ├── ModifySubnetAttributeOptions.java │ │ │ │ ├── RequestSpotInstancesOptions.java │ │ │ │ ├── RouteOptions.java │ │ │ │ ├── RouteTableOptions.java │ │ │ │ └── Tenancy.java │ │ │ ├── predicates/ │ │ │ │ ├── PlacementGroupAvailable.java │ │ │ │ ├── PlacementGroupDeleted.java │ │ │ │ └── SpotInstanceRequestActive.java │ │ │ ├── reference/ │ │ │ │ └── AWSEC2Constants.java │ │ │ └── xml/ │ │ │ ├── AWSDescribeInstancesResponseHandler.java │ │ │ ├── AWSEC2DescribeSecurityGroupsResponseHandler.java │ │ │ ├── AWSEC2IpPermissionHandler.java │ │ │ ├── AWSEC2SecurityGroupHandler.java │ │ │ ├── AWSRunInstancesResponseHandler.java │ │ │ ├── AssociateRouteTableResponseHandler.java │ │ │ ├── BaseAWSReservationHandler.java │ │ │ ├── CreateRouteTableResponseHandler.java │ │ │ ├── CreateSecurityGroupResponseHandler.java │ │ │ ├── DescribeInternetGatewaysResponseHandler.java │ │ │ ├── DescribePlacementGroupsResponseHandler.java │ │ │ ├── DescribeReservedInstancesOfferingResponseHandler.java │ │ │ ├── DescribeRouteTablesResponseHandler.java │ │ │ ├── DescribeSpotPriceHistoryResponseHandler.java │ │ │ ├── DescribeVPCsResponseHandler.java │ │ │ ├── InternetGatewayAttachmentSetHandler.java │ │ │ ├── InternetGatewayHandler.java │ │ │ ├── LaunchSpecificationHandler.java │ │ │ ├── MonitoringStateHandler.java │ │ │ ├── PlacementGroupHandler.java │ │ │ ├── ProductCodesHandler.java │ │ │ ├── ReservedInstancesOfferingHandler.java │ │ │ ├── ReturnValueHandler.java │ │ │ ├── RouteHandler.java │ │ │ ├── RouteSetHandler.java │ │ │ ├── RouteTableAssociationSetHandler.java │ │ │ ├── RouteTableHandler.java │ │ │ ├── SpotHandler.java │ │ │ ├── SpotInstanceHandler.java │ │ │ ├── SpotInstancesHandler.java │ │ │ └── VPCHandler.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── aws/ │ │ │ └── ec2/ │ │ │ ├── AWSEC2ContextBuilderTest.java │ │ │ ├── AWSEC2ProviderTest.java │ │ │ ├── binders/ │ │ │ │ ├── BindLaunchSpecificationToFormParamsTest.java │ │ │ │ └── BindTagsToIndexedFormParamsTest.java │ │ │ ├── compute/ │ │ │ │ ├── AWSEC2ComputeServiceApiMockTest.java │ │ │ │ ├── AWSEC2ComputeServiceLiveTest.java │ │ │ │ ├── AWSEC2TemplateBuilderLiveTest.java │ │ │ │ ├── config/ │ │ │ │ │ └── AWSEC2ComputeServiceContextModuleTest.java │ │ │ │ ├── extensions/ │ │ │ │ │ ├── AWSEC2ImageExtensionLiveTest.java │ │ │ │ │ ├── AWSEC2SecurityGroupExtensionApiMockTest.java │ │ │ │ │ └── AWSEC2SecurityGroupExtensionLiveTest.java │ │ │ │ ├── functions/ │ │ │ │ │ ├── AWSEC2SecurityGroupToSecurityGroupTest.java │ │ │ │ │ ├── AWSRunningInstanceToNodeMetadataTest.java │ │ │ │ │ └── PresentSpotRequestsAndInstancesTest.java │ │ │ │ ├── loaders/ │ │ │ │ │ └── AWSEC2CreateSecurityGroupIfNeededTest.java │ │ │ │ ├── options/ │ │ │ │ │ └── AWSEC2TemplateOptionsTest.java │ │ │ │ └── strategy/ │ │ │ │ ├── AWSEC2IOExceptionRetryHandlerTest.java │ │ │ │ ├── AWSEC2ImageParserTest.java │ │ │ │ ├── AWSEC2ReviseParsedImageTest.java │ │ │ │ └── CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsTest.java │ │ │ ├── features/ │ │ │ │ ├── AWSAMIApiLiveTest.java │ │ │ │ ├── AWSAMIApiMockTest.java │ │ │ │ ├── AWSElasticBlockStoreApiLiveTest.java │ │ │ │ ├── AWSInstanceApiLiveTest.java │ │ │ │ ├── AWSInstanceApiTest.java │ │ │ │ ├── AWSKeyPairApiLiveTest.java │ │ │ │ ├── AWSKeyPairApiTest.java │ │ │ │ ├── AWSSecurityGroupApiLiveTest.java │ │ │ │ ├── AWSSecurityGroupApiMockTest.java │ │ │ │ ├── AWSSecurityGroupApiTest.java │ │ │ │ ├── AWSSubnetApiLiveTest.java │ │ │ │ ├── AWSSubnetApiMockTest.java │ │ │ │ ├── BaseAWSEC2ApiTest.java │ │ │ │ ├── InternetGatewayApiLiveTest.java │ │ │ │ ├── InternetGatewayApiMockTest.java │ │ │ │ ├── MonitoringApiLiveTest.java │ │ │ │ ├── MonitoringApiMockTest.java │ │ │ │ ├── PlacementGroupApiLiveTest.java │ │ │ │ ├── PlacementGroupApiMockTest.java │ │ │ │ ├── RouteTableApiLiveTest.java │ │ │ │ ├── RouteTableApiMockTest.java │ │ │ │ ├── SpotInstanceApiLiveTest.java │ │ │ │ ├── SpotInstanceApiMockTest.java │ │ │ │ ├── TagSecurityGroupLiveTest.java │ │ │ │ ├── VPCApiLiveTest.java │ │ │ │ └── VPCApiMockTest.java │ │ │ ├── functions/ │ │ │ │ ├── ImportOrReturnExistingKeypairTest.java │ │ │ │ └── SpotInstanceRequestToAWSRunningInstanceTest.java │ │ │ ├── internal/ │ │ │ │ └── BaseAWSEC2ApiMockTest.java │ │ │ ├── options/ │ │ │ │ ├── AWSDescribeImagesOptionsTest.java │ │ │ │ ├── AWSRunInstancesOptionsTest.java │ │ │ │ ├── DescribeSpotPriceHistoryOptionsTest.java │ │ │ │ └── RequestSpotInstancesOptionsTest.java │ │ │ ├── parse/ │ │ │ │ ├── DescribeInstancesResponseTest.java │ │ │ │ └── DescribeSecurityGroupsResponseTest.java │ │ │ └── xml/ │ │ │ ├── AWSDescribeInstancesResponseHandlerTest.java │ │ │ ├── AWSRunInstancesResponseHandlerTest.java │ │ │ ├── DescribePlacementGroupsResponseHandlerTest.java │ │ │ ├── DescribeReservedInstancesOfferingResponseHandlerTest.java │ │ │ ├── DescribeSpotPriceHistoryResponseHandlerTest.java │ │ │ ├── MonitoringStateHandlerTest.java │ │ │ ├── ProductCodesHandlerTest.java │ │ │ ├── SpotInstanceHandlerTest.java │ │ │ └── SpotInstancesHandlerTest.java │ │ └── resources/ │ │ ├── alestic_canonical.xml │ │ ├── amzn_images.xml │ │ ├── associate_route_table.xml │ │ ├── attach_internet_gateway.xml │ │ ├── attach_internet_gateway_failed.xml │ │ ├── centos_marketplace_images.xml │ │ ├── create_internet_gateway.xml │ │ ├── create_route.xml │ │ ├── create_route_table.xml │ │ ├── create_vpc.xml │ │ ├── delete_internet_gateway.xml │ │ ├── delete_route.xml │ │ ├── delete_route_table.xml │ │ ├── delete_vpc.xml │ │ ├── describe_image_attribute_productCodes.xml │ │ ├── describe_images_cc.xml │ │ ├── describe_instances_1.xml │ │ ├── describe_instances_2.xml │ │ ├── describe_instances_3.xml │ │ ├── describe_instances_latest.xml │ │ ├── describe_instances_pending.xml │ │ ├── describe_internet_gateways.xml │ │ ├── describe_placement_groups.xml │ │ ├── describe_placement_groups_empty.xml │ │ ├── describe_reserved_instances_offerings.xml │ │ ├── describe_route_tables.xml │ │ ├── describe_route_tables_invalid.xml │ │ ├── describe_security_groups_vpc.xml │ │ ├── describe_spot_instance.xml │ │ ├── describe_spot_instance_requests.xml │ │ ├── describe_spot_instance_tags.xml │ │ ├── describe_spot_instances_1.xml │ │ ├── describe_spot_price_history.xml │ │ ├── describe_vpcs.xml │ │ ├── detach_internet_gateway.xml │ │ ├── disassociate_route_table.xml │ │ ├── dry_run.xml │ │ ├── get_internet_gateway.xml │ │ ├── logback-test.xml │ │ ├── monitoring.xml │ │ ├── replace_route.xml │ │ ├── request_spot_instances-ebs.xml │ │ ├── request_spot_instances.xml │ │ ├── rightscale_images.xml │ │ ├── run_instances_1.xml │ │ └── vostok.xml │ ├── aws-route53/ │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── aws/ │ │ │ └── route53/ │ │ │ └── AWSRoute53ProviderMetadata.java │ │ └── test/ │ │ └── java/ │ │ └── org/ │ │ └── jclouds/ │ │ └── aws/ │ │ └── route53/ │ │ ├── AWSRoute53ApiLiveTest.java │ │ ├── AWSRoute53ProviderTest.java │ │ └── features/ │ │ ├── AWSHostedZoneApiLiveTest.java │ │ └── AWSResourceRecordSetApiLiveTest.java │ ├── aws-s3/ │ │ ├── README.md │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── aws/ │ │ │ └── s3/ │ │ │ ├── AWSS3ApiMetadata.java │ │ │ ├── AWSS3Client.java │ │ │ ├── AWSS3ProviderMetadata.java │ │ │ ├── blobstore/ │ │ │ │ ├── AWSS3BlobRequestSignerV4.java │ │ │ │ ├── AWSS3BlobStore.java │ │ │ │ ├── AWSS3BlobStoreContext.java │ │ │ │ ├── config/ │ │ │ │ │ └── AWSS3BlobStoreContextModule.java │ │ │ │ ├── internal/ │ │ │ │ │ └── AWSS3BlobStoreContextImpl.java │ │ │ │ └── options/ │ │ │ │ ├── AWSS3PutObjectOptions.java │ │ │ │ └── AWSS3PutOptions.java │ │ │ ├── config/ │ │ │ │ └── AWSS3HttpApiModule.java │ │ │ ├── filters/ │ │ │ │ ├── AWSRequestAuthorizeSignature.java │ │ │ │ ├── AWSRequestAuthorizeSignatureV4.java │ │ │ │ └── package-info.java │ │ │ └── predicates/ │ │ │ └── validators/ │ │ │ └── AWSS3BucketNameValidator.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── aws/ │ │ │ └── s3/ │ │ │ ├── AWSS3ClientExpectTest.java │ │ │ ├── AWSS3ClientLiveTest.java │ │ │ ├── AWSS3ClientTest.java │ │ │ ├── AWSS3ProviderTest.java │ │ │ ├── blobstore/ │ │ │ │ ├── AWSS3BlobSignerExpectTest.java │ │ │ │ ├── AWSS3BlobSignerV4ExpectTest.java │ │ │ │ └── integration/ │ │ │ │ ├── AWSS3BlobIntegrationLiveTest.java │ │ │ │ ├── AWSS3BlobLiveTest.java │ │ │ │ ├── AWSS3BlobSignerLiveTest.java │ │ │ │ ├── AWSS3ContainerIntegrationLiveTest.java │ │ │ │ ├── AWSS3ContainerLiveTest.java │ │ │ │ ├── AWSS3ServiceIntegrationLiveTest.java │ │ │ │ └── PathBasedContainerLiveTest.java │ │ │ ├── filter/ │ │ │ │ └── AwsRequestAuthorizeSignatureV4Test.java │ │ │ ├── internal/ │ │ │ │ └── BaseAWSS3ClientExpectTest.java │ │ │ └── services/ │ │ │ └── AWSBucketsLiveTest.java │ │ └── resources/ │ │ └── log4j.xml │ ├── aws-sqs/ │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── aws/ │ │ │ └── sqs/ │ │ │ └── AWSSQSProviderMetadata.java │ │ └── test/ │ │ └── java/ │ │ └── org/ │ │ └── jclouds/ │ │ └── aws/ │ │ └── sqs/ │ │ ├── AWSSQSProviderTest.java │ │ └── features/ │ │ ├── AWSMessageApiLiveTest.java │ │ ├── AWSPermissionApiLiveTest.java │ │ └── AWSQueueApiLiveTest.java │ ├── aws-sts/ │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── aws/ │ │ │ └── sts/ │ │ │ └── AWSSTSProviderMetadata.java │ │ └── test/ │ │ └── java/ │ │ └── org/ │ │ └── jclouds/ │ │ └── aws/ │ │ └── sts/ │ │ ├── AWSSTSApiLiveTest.java │ │ └── AWSSTSProviderTest.java │ ├── azureblob/ │ │ ├── README.md │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ ├── azure/ │ │ │ │ └── storage/ │ │ │ │ ├── AzureStorageResponseException.java │ │ │ │ ├── config/ │ │ │ │ │ ├── AuthType.java │ │ │ │ │ ├── AzureStorageOAuthConfigFactory.java │ │ │ │ │ └── AzureStorageProperties.java │ │ │ │ ├── domain/ │ │ │ │ │ ├── AzureStorageError.java │ │ │ │ │ ├── BoundedSet.java │ │ │ │ │ └── internal/ │ │ │ │ │ └── BoundedHashSet.java │ │ │ │ ├── filters/ │ │ │ │ │ └── SharedKeyLiteAuthentication.java │ │ │ │ ├── handlers/ │ │ │ │ │ ├── AzureStorageClientErrorRetryHandler.java │ │ │ │ │ └── ParseAzureStorageErrorFromXmlContent.java │ │ │ │ ├── options/ │ │ │ │ │ ├── CreateOptions.java │ │ │ │ │ └── ListOptions.java │ │ │ │ ├── reference/ │ │ │ │ │ └── AzureStorageHeaders.java │ │ │ │ ├── util/ │ │ │ │ │ ├── AzureStorageUtils.java │ │ │ │ │ └── storageurl/ │ │ │ │ │ ├── AppendAccountToEndpoint.java │ │ │ │ │ ├── StorageAccountInVhost.java │ │ │ │ │ ├── StorageUrlSupplier.java │ │ │ │ │ └── TrailingSlashUtil.java │ │ │ │ └── xml/ │ │ │ │ └── ErrorHandler.java │ │ │ └── azureblob/ │ │ │ ├── AzureBlobApiMetadata.java │ │ │ ├── AzureBlobClient.java │ │ │ ├── AzureBlobFallbacks.java │ │ │ ├── AzureBlobProviderMetadata.java │ │ │ ├── binders/ │ │ │ │ ├── BindAzureBlobMetadataToMultipartRequest.java │ │ │ │ ├── BindAzureBlobMetadataToRequest.java │ │ │ │ ├── BindAzureBlocksToRequest.java │ │ │ │ ├── BindAzureContentMetadataToRequest.java │ │ │ │ ├── BindAzureCopyOptionsToRequest.java │ │ │ │ └── BindPublicAccessToRequest.java │ │ │ ├── blobstore/ │ │ │ │ ├── AzureBlobRequestSigner.java │ │ │ │ ├── AzureBlobStore.java │ │ │ │ ├── config/ │ │ │ │ │ └── AzureBlobStoreContextModule.java │ │ │ │ └── functions/ │ │ │ │ ├── AzureBlobToBlob.java │ │ │ │ ├── BlobMetadataToBlobProperties.java │ │ │ │ ├── BlobPropertiesToBlobMetadata.java │ │ │ │ ├── BlobToAzureBlob.java │ │ │ │ ├── ContainerToResourceMetadata.java │ │ │ │ ├── ListBlobsResponseToResourceList.java │ │ │ │ └── ListOptionsToListBlobsOptions.java │ │ │ ├── config/ │ │ │ │ ├── AppendAccountToEndpointModule.java │ │ │ │ ├── AzureBlobHttpApiModule.java │ │ │ │ ├── AzureBlobModule.java │ │ │ │ └── InsufficientAccessRightsException.java │ │ │ ├── domain/ │ │ │ │ ├── AccessTier.java │ │ │ │ ├── AzureBlob.java │ │ │ │ ├── BlobBlockProperties.java │ │ │ │ ├── BlobProperties.java │ │ │ │ ├── BlobType.java │ │ │ │ ├── ContainerProperties.java │ │ │ │ ├── LeaseStatus.java │ │ │ │ ├── ListBlobBlocksResponse.java │ │ │ │ ├── ListBlobsInclude.java │ │ │ │ ├── ListBlobsResponse.java │ │ │ │ ├── MutableBlobProperties.java │ │ │ │ ├── MutableContainerPropertiesWithMetadata.java │ │ │ │ ├── PublicAccess.java │ │ │ │ └── internal/ │ │ │ │ ├── AzureBlobImpl.java │ │ │ │ ├── BlobBlockPropertiesImpl.java │ │ │ │ ├── BlobPropertiesImpl.java │ │ │ │ ├── ContainerPropertiesImpl.java │ │ │ │ ├── HashSetListBlobsResponse.java │ │ │ │ ├── ListBlobBlocksResponseImpl.java │ │ │ │ ├── MutableBlobPropertiesImpl.java │ │ │ │ └── MutableContainerPropertiesWithMetadataImpl.java │ │ │ ├── functions/ │ │ │ │ ├── BlobName.java │ │ │ │ ├── ParseBlobFromHeadersAndHttpContent.java │ │ │ │ ├── ParseBlobPropertiesFromHeaders.java │ │ │ │ ├── ParseContainerPropertiesFromHeaders.java │ │ │ │ └── ParsePublicAccessHeader.java │ │ │ ├── handlers/ │ │ │ │ └── ParseAzureBlobErrorFromXmlContent.java │ │ │ ├── options/ │ │ │ │ ├── CopyBlobOptions.java │ │ │ │ ├── CreateContainerOptions.java │ │ │ │ └── ListBlobsOptions.java │ │ │ ├── predicates/ │ │ │ │ └── validators/ │ │ │ │ ├── BlockIdValidator.java │ │ │ │ └── ContainerNameValidator.java │ │ │ └── xml/ │ │ │ ├── AccountNameEnumerationResultsHandler.java │ │ │ ├── BlobBlocksResultsHandler.java │ │ │ └── ContainerNameEnumerationResultsHandler.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ ├── azure/ │ │ │ │ └── storage/ │ │ │ │ ├── filters/ │ │ │ │ │ └── SharedKeyLiteAuthenticationTest.java │ │ │ │ ├── handlers/ │ │ │ │ │ ├── ParseAzureBlobErrorFromXmlContentTest.java │ │ │ │ │ └── ParseAzureErrorFromXmlContentTest.java │ │ │ │ ├── options/ │ │ │ │ │ ├── CreateOptionsTest.java │ │ │ │ │ └── ListOptionsTest.java │ │ │ │ ├── util/ │ │ │ │ │ └── storageurl/ │ │ │ │ │ ├── AppendAccountToEndpointTest.java │ │ │ │ │ └── StorageAccountInVhostTest.java │ │ │ │ └── xml/ │ │ │ │ └── ErrorHandlerTest.java │ │ │ └── azureblob/ │ │ │ ├── AzureBlobClientAdTest.java │ │ │ ├── AzureBlobClientLiveTest.java │ │ │ ├── AzureBlobClientTest.java │ │ │ ├── AzureBlobProviderTest.java │ │ │ ├── binders/ │ │ │ │ └── BindAzureBlobMetadataToRequestTest.java │ │ │ ├── blobstore/ │ │ │ │ ├── AzureBlobRequestSignerTest.java │ │ │ │ ├── AzureBlobStoreTest.java │ │ │ │ ├── functions/ │ │ │ │ │ ├── ListBlobsOptionsToListOptions.java │ │ │ │ │ └── ResourceToListBlobsResponse.java │ │ │ │ └── integration/ │ │ │ │ ├── AzureBlobContainerIntegrationLiveTest.java │ │ │ │ ├── AzureBlobContainerLiveTest.java │ │ │ │ ├── AzureBlobIntegrationLiveTest.java │ │ │ │ ├── AzureBlobLiveTest.java │ │ │ │ ├── AzureBlobServiceIntegrationLiveTest.java │ │ │ │ └── AzureBlobSignerLiveTest.java │ │ │ ├── config/ │ │ │ │ └── AzureBlobHttpApiModuleTest.java │ │ │ ├── options/ │ │ │ │ ├── CreateContainerOptionsTest.java │ │ │ │ └── ListBlobsOptionsTest.java │ │ │ ├── predicates/ │ │ │ │ └── validators/ │ │ │ │ └── ContainerNameValidatorTest.java │ │ │ └── xml/ │ │ │ ├── AccountNameEnumerationResultsHandlerTest.java │ │ │ ├── BlobBlocksResultsHandlerTest.java │ │ │ └── ContainerNameEnumerationResultsHandlerTest.java │ │ └── resources/ │ │ ├── log4j.xml │ │ ├── test_error.xml │ │ ├── test_list_blob_blocks.xml │ │ ├── test_list_blobs.xml │ │ ├── test_list_blobs_options.xml │ │ ├── test_list_containers.xml │ │ └── test_list_containers_options.xml │ ├── azurecompute-arm/ │ │ ├── README.md │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── azurecompute/ │ │ │ └── arm/ │ │ │ ├── AzureComputeApi.java │ │ │ ├── AzureComputeProviderMetadata.java │ │ │ ├── AzureManagementApiMetadata.java │ │ │ ├── compute/ │ │ │ │ ├── AzureComputeService.java │ │ │ │ ├── AzureComputeServiceAdapter.java │ │ │ │ ├── config/ │ │ │ │ │ ├── AzureComputeServiceContextModule.java │ │ │ │ │ ├── AzureNameValidator.java │ │ │ │ │ └── AzurePredicatesModule.java │ │ │ │ ├── domain/ │ │ │ │ │ ├── LocationAndName.java │ │ │ │ │ ├── ResourceGroupAndName.java │ │ │ │ │ └── ResourceGroupAndNameAndIngressRules.java │ │ │ │ ├── extensions/ │ │ │ │ │ ├── AzureComputeImageExtension.java │ │ │ │ │ └── AzureComputeSecurityGroupExtension.java │ │ │ │ ├── functions/ │ │ │ │ │ ├── CustomImageToVMImage.java │ │ │ │ │ ├── LocationToLocation.java │ │ │ │ │ ├── LocationToResourceGroupName.java │ │ │ │ │ ├── NetworkSecurityGroupToSecurityGroup.java │ │ │ │ │ ├── NetworkSecurityRuleToIpPermission.java │ │ │ │ │ ├── TemplateToAvailabilitySet.java │ │ │ │ │ ├── VMHardwareToHardware.java │ │ │ │ │ ├── VMImageToImage.java │ │ │ │ │ ├── VirtualMachineToNodeMetadata.java │ │ │ │ │ └── VirtualMachineToStatus.java │ │ │ │ ├── loaders/ │ │ │ │ │ ├── CreateSecurityGroupIfNeeded.java │ │ │ │ │ └── DefaultResourceGroup.java │ │ │ │ ├── options/ │ │ │ │ │ ├── AzureTemplateOptions.java │ │ │ │ │ └── IpOptions.java │ │ │ │ └── strategy/ │ │ │ │ ├── CleanupResources.java │ │ │ │ └── CreateResourcesThenCreateNodes.java │ │ │ ├── config/ │ │ │ │ ├── AzureComputeHttpApiModule.java │ │ │ │ ├── AzureComputeParserModule.java │ │ │ │ ├── AzureComputeProperties.java │ │ │ │ ├── AzureComputeRateLimitModule.java │ │ │ │ ├── AzureOAuthConfigFactory.java │ │ │ │ ├── GraphRBAC.java │ │ │ │ ├── OAuthResource.java │ │ │ │ └── Tenant.java │ │ │ ├── domain/ │ │ │ │ ├── ActionGroup.java │ │ │ │ ├── ActionStatus.java │ │ │ │ ├── Actions.java │ │ │ │ ├── ActivityLogAlert.java │ │ │ │ ├── ActivityLogAlertProperties.java │ │ │ │ ├── AddressSpace.java │ │ │ │ ├── Alert.java │ │ │ │ ├── AlertModification.java │ │ │ │ ├── AlertModificationEvent.java │ │ │ │ ├── AlertModificationItem.java │ │ │ │ ├── AlertModificationProperties.java │ │ │ │ ├── AlertProperties.java │ │ │ │ ├── AlertRuleAllOfCondition.java │ │ │ │ ├── AlertRuleAnyOfOrLeafCondition.java │ │ │ │ ├── AlertRuleLeafCondition.java │ │ │ │ ├── AlertSummary.java │ │ │ │ ├── AlertSummaryGroup.java │ │ │ │ ├── AlertSummaryGroupItem.java │ │ │ │ ├── Availability.java │ │ │ │ ├── AvailabilitySet.java │ │ │ │ ├── BackendAddressPool.java │ │ │ │ ├── BackendAddressPoolProperties.java │ │ │ │ ├── Certificate.java │ │ │ │ ├── ComputeNode.java │ │ │ │ ├── CreationData.java │ │ │ │ ├── Criteria.java │ │ │ │ ├── DataDisk.java │ │ │ │ ├── Deployment.java │ │ │ │ ├── DeploymentBody.java │ │ │ │ ├── DeploymentProperties.java │ │ │ │ ├── DeploymentTemplate.java │ │ │ │ ├── DiagnosticsProfile.java │ │ │ │ ├── Disk.java │ │ │ │ ├── DiskProperties.java │ │ │ │ ├── DiskSku.java │ │ │ │ ├── DnsSettings.java │ │ │ │ ├── DynamicThresholdFailingPeriods.java │ │ │ │ ├── Error.java │ │ │ │ ├── Essentials.java │ │ │ │ ├── Extension.java │ │ │ │ ├── ExtensionProfile.java │ │ │ │ ├── ExtensionProfileSettings.java │ │ │ │ ├── ExtensionProperties.java │ │ │ │ ├── FrontendIPConfigurations.java │ │ │ │ ├── FrontendIPConfigurationsProperties.java │ │ │ │ ├── HardwareProfile.java │ │ │ │ ├── IdReference.java │ │ │ │ ├── Image.java │ │ │ │ ├── ImageProperties.java │ │ │ │ ├── ImageReference.java │ │ │ │ ├── InboundNatRule.java │ │ │ │ ├── InboundNatRuleProperties.java │ │ │ │ ├── IpAddressAvailabilityResult.java │ │ │ │ ├── IpAllocationMethod.java │ │ │ │ ├── IpConfiguration.java │ │ │ │ ├── IpConfigurationProperties.java │ │ │ │ ├── Key.java │ │ │ │ ├── KeyVaultReference.java │ │ │ │ ├── Location.java │ │ │ │ ├── ManagedDiskParameters.java │ │ │ │ ├── Metric.java │ │ │ │ ├── MetricAlert.java │ │ │ │ ├── MetricAlertAction.java │ │ │ │ ├── MetricAlertCriteria.java │ │ │ │ ├── MetricAlertProperties.java │ │ │ │ ├── MetricData.java │ │ │ │ ├── MetricDefinition.java │ │ │ │ ├── MetricDimension.java │ │ │ │ ├── MetricName.java │ │ │ │ ├── NetworkInterfaceCard.java │ │ │ │ ├── NetworkInterfaceCardProperties.java │ │ │ │ ├── NetworkInterfaceConfiguration.java │ │ │ │ ├── NetworkInterfaceConfigurationProperties.java │ │ │ │ ├── NetworkProfile.java │ │ │ │ ├── NetworkSecurityGroup.java │ │ │ │ ├── NetworkSecurityGroupProperties.java │ │ │ │ ├── NetworkSecurityRule.java │ │ │ │ ├── NetworkSecurityRuleProperties.java │ │ │ │ ├── OSDisk.java │ │ │ │ ├── OSProfile.java │ │ │ │ ├── Offer.java │ │ │ │ ├── Plan.java │ │ │ │ ├── Probe.java │ │ │ │ ├── ProbeProperties.java │ │ │ │ ├── Provisionable.java │ │ │ │ ├── Publisher.java │ │ │ │ ├── Region.java │ │ │ │ ├── Resource.java │ │ │ │ ├── ResourceDefinition.java │ │ │ │ ├── ResourceGroup.java │ │ │ │ ├── ResourceProviderMetaData.java │ │ │ │ ├── SKU.java │ │ │ │ ├── Secret.java │ │ │ │ ├── Secrets.java │ │ │ │ ├── ServicePrincipal.java │ │ │ │ ├── Status.java │ │ │ │ ├── StorageAccountType.java │ │ │ │ ├── StorageProfile.java │ │ │ │ ├── StorageService.java │ │ │ │ ├── StorageServiceKeys.java │ │ │ │ ├── StorageServiceUpdateParams.java │ │ │ │ ├── Subnet.java │ │ │ │ ├── TemplateParameterType.java │ │ │ │ ├── VHD.java │ │ │ │ ├── VMDeployment.java │ │ │ │ ├── VMHardware.java │ │ │ │ ├── VMImage.java │ │ │ │ ├── VMSize.java │ │ │ │ ├── Value.java │ │ │ │ ├── Vault.java │ │ │ │ ├── VaultCertificate.java │ │ │ │ ├── VaultProperties.java │ │ │ │ ├── Version.java │ │ │ │ ├── VirtualMachine.java │ │ │ │ ├── VirtualMachineInstance.java │ │ │ │ ├── VirtualMachineProperties.java │ │ │ │ ├── VirtualMachineScaleSet.java │ │ │ │ ├── VirtualMachineScaleSetDNSSettings.java │ │ │ │ ├── VirtualMachineScaleSetIpConfiguration.java │ │ │ │ ├── VirtualMachineScaleSetIpConfigurationProperties.java │ │ │ │ ├── VirtualMachineScaleSetNetworkProfile.java │ │ │ │ ├── VirtualMachineScaleSetNetworkSecurityGroup.java │ │ │ │ ├── VirtualMachineScaleSetOSProfile.java │ │ │ │ ├── VirtualMachineScaleSetPlan.java │ │ │ │ ├── VirtualMachineScaleSetProperties.java │ │ │ │ ├── VirtualMachineScaleSetPublicIPAddressConfiguration.java │ │ │ │ ├── VirtualMachineScaleSetPublicIPAddressProperties.java │ │ │ │ ├── VirtualMachineScaleSetSKU.java │ │ │ │ ├── VirtualMachineScaleSetUpgradeMode.java │ │ │ │ ├── VirtualMachineScaleSetUpgradePolicy.java │ │ │ │ ├── VirtualMachineScaleSetVirtualMachineProfile.java │ │ │ │ ├── VirtualNetwork.java │ │ │ │ ├── loadbalancer/ │ │ │ │ │ ├── LoadBalancer.java │ │ │ │ │ ├── LoadBalancerProperties.java │ │ │ │ │ ├── LoadBalancingRule.java │ │ │ │ │ └── LoadBalancingRuleProperties.java │ │ │ │ ├── publicipaddress/ │ │ │ │ │ ├── PublicIPAddress.java │ │ │ │ │ └── PublicIPAddressProperties.java │ │ │ │ └── vpn/ │ │ │ │ ├── BGPSettings.java │ │ │ │ ├── DHGroup.java │ │ │ │ ├── IPSecEncryption.java │ │ │ │ ├── IPSecIntegrity.java │ │ │ │ ├── IPSecPolicy.java │ │ │ │ ├── IkeEncryption.java │ │ │ │ ├── IkeIntegrity.java │ │ │ │ ├── LocalNetworkGateway.java │ │ │ │ ├── LocalNetworkGatewayProperties.java │ │ │ │ ├── PFSGroup.java │ │ │ │ ├── SKU.java │ │ │ │ ├── TunnelConnectionHealth.java │ │ │ │ ├── VPNClientConfiguration.java │ │ │ │ ├── VPNClientRevokedCertificate.java │ │ │ │ ├── VPNClientRootCertificate.java │ │ │ │ ├── VPNType.java │ │ │ │ ├── VirtualNetworkGateway.java │ │ │ │ ├── VirtualNetworkGatewayConnection.java │ │ │ │ ├── VirtualNetworkGatewayConnectionProperties.java │ │ │ │ ├── VirtualNetworkGatewayProperties.java │ │ │ │ └── VirtualNetworkGatewayType.java │ │ │ ├── exceptions/ │ │ │ │ └── AzureComputeRateLimitExceededException.java │ │ │ ├── features/ │ │ │ │ ├── ActivityLogAlertApi.java │ │ │ │ ├── AlertApi.java │ │ │ │ ├── AvailabilitySetApi.java │ │ │ │ ├── DeploymentApi.java │ │ │ │ ├── DiskApi.java │ │ │ │ ├── GraphRBACApi.java │ │ │ │ ├── ImageApi.java │ │ │ │ ├── JobApi.java │ │ │ │ ├── LoadBalancerApi.java │ │ │ │ ├── LocalNetworkGatewayApi.java │ │ │ │ ├── LocationApi.java │ │ │ │ ├── MetricAlertApi.java │ │ │ │ ├── MetricDefinitionsApi.java │ │ │ │ ├── MetricsApi.java │ │ │ │ ├── NetworkInterfaceCardApi.java │ │ │ │ ├── NetworkSecurityGroupApi.java │ │ │ │ ├── NetworkSecurityRuleApi.java │ │ │ │ ├── OSImageApi.java │ │ │ │ ├── PublicIPAddressApi.java │ │ │ │ ├── ResourceGroupApi.java │ │ │ │ ├── ResourceProviderApi.java │ │ │ │ ├── StorageAccountApi.java │ │ │ │ ├── SubnetApi.java │ │ │ │ ├── VMSizeApi.java │ │ │ │ ├── VaultApi.java │ │ │ │ ├── VirtualMachineApi.java │ │ │ │ ├── VirtualMachineScaleSetApi.java │ │ │ │ ├── VirtualNetworkApi.java │ │ │ │ ├── VirtualNetworkGatewayApi.java │ │ │ │ └── VirtualNetworkGatewayConnectionApi.java │ │ │ ├── filters/ │ │ │ │ └── ApiVersionFilter.java │ │ │ ├── functions/ │ │ │ │ ├── FalseOn204.java │ │ │ │ ├── ParseJobStatus.java │ │ │ │ ├── StatusCodeParser.java │ │ │ │ └── URIParser.java │ │ │ ├── handlers/ │ │ │ │ ├── AzureComputeErrorHandler.java │ │ │ │ ├── AzureRateLimitRetryHandler.java │ │ │ │ └── AzureRetryableErrorHandler.java │ │ │ ├── options/ │ │ │ │ └── AlertRequestOptions.java │ │ │ ├── reference/ │ │ │ │ └── AlertQueryParams.java │ │ │ └── util/ │ │ │ ├── GetEnumValue.java │ │ │ └── VMImages.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── azurecompute/ │ │ │ └── arm/ │ │ │ ├── AzureComputeProviderMetadataTest.java │ │ │ ├── compute/ │ │ │ │ ├── AzureComputeServiceLiveTest.java │ │ │ │ ├── AzureTemplateBuilderLiveTest.java │ │ │ │ ├── extensions/ │ │ │ │ │ ├── AzureComputeImageExtensionLiveTest.java │ │ │ │ │ └── AzureComputeSecurityGroupExtensionLiveTest.java │ │ │ │ ├── functions/ │ │ │ │ │ └── VirtualMachineToStatusTest.java │ │ │ │ └── strategy/ │ │ │ │ └── CreateResourcesThenCreateNodesTest.java │ │ │ ├── config/ │ │ │ │ ├── AzureNameValidatorTest.java │ │ │ │ ├── IsChinaEndpointTest.java │ │ │ │ └── ParseTenantIdTest.java │ │ │ ├── domain/ │ │ │ │ ├── IdReferenceTest.java │ │ │ │ └── SubnetTest.java │ │ │ ├── features/ │ │ │ │ ├── ActivityLogAlertApiLiveTest.java │ │ │ │ ├── ActivityLogAlertApiMockTest.java │ │ │ │ ├── AlertApiLiveTest.java │ │ │ │ ├── AlertApiMockTest.java │ │ │ │ ├── AvailabilitySetApiLiveTest.java │ │ │ │ ├── AvailabilitySetApiMockTest.java │ │ │ │ ├── DeploymentApiLiveTest.java │ │ │ │ ├── DeploymentApiMockTest.java │ │ │ │ ├── DiskApiLiveTest.java │ │ │ │ ├── DiskApiMockTest.java │ │ │ │ ├── GraphRBACApiLiveTest.java │ │ │ │ ├── GraphRBACApiMockTest.java │ │ │ │ ├── ImageApiLiveTest.java │ │ │ │ ├── ImageApiMockTest.java │ │ │ │ ├── JobApiMockTest.java │ │ │ │ ├── LoadBalancerApiLiveTest.java │ │ │ │ ├── LoadBalancerApiMockTest.java │ │ │ │ ├── LocalNetworkGatewayApiLiveTest.java │ │ │ │ ├── LocalNetworkGatewayApiMockTest.java │ │ │ │ ├── LocationApiLiveTest.java │ │ │ │ ├── LocationApiMockTest.java │ │ │ │ ├── MetricAlertApiLiveTest.java │ │ │ │ ├── MetricAlertApiMockTest.java │ │ │ │ ├── MetricDefinitionsApiLiveTest.java │ │ │ │ ├── MetricDefinitionsApiMockTest.java │ │ │ │ ├── MetricsApiLiveTest.java │ │ │ │ ├── MetricsApiMockTest.java │ │ │ │ ├── NetworkInterfaceCardApiLiveTest.java │ │ │ │ ├── NetworkInterfaceCardApiMockTest.java │ │ │ │ ├── NetworkSecurityGroupApiLiveTest.java │ │ │ │ ├── NetworkSecurityGroupApiMockTest.java │ │ │ │ ├── NetworkSecurityRuleApiLiveTest.java │ │ │ │ ├── NetworkSecurityRuleApiMockTest.java │ │ │ │ ├── OSImageApiLiveTest.java │ │ │ │ ├── OSImageApiMockTest.java │ │ │ │ ├── PublicIPAddressApiLiveTest.java │ │ │ │ ├── PublicIPAddressApiMockTest.java │ │ │ │ ├── ResourceGroupApiLiveTest.java │ │ │ │ ├── ResourceGroupApiMockTest.java │ │ │ │ ├── ResourceProviderAPIMockTest.java │ │ │ │ ├── ResourceProviderApiLiveTest.java │ │ │ │ ├── StorageAccountApiLiveTest.java │ │ │ │ ├── StorageAccountApiMockTest.java │ │ │ │ ├── SubnetApiLiveTest.java │ │ │ │ ├── SubnetApiMockTest.java │ │ │ │ ├── VMSizeApiLiveTest.java │ │ │ │ ├── VMSizeApiMockTest.java │ │ │ │ ├── VaultApiLiveTest.java │ │ │ │ ├── VaultApiMockTest.java │ │ │ │ ├── VirtualMachineApiLiveTest.java │ │ │ │ ├── VirtualMachineApiMockTest.java │ │ │ │ ├── VirtualMachineScaleSetApiLiveTest.java │ │ │ │ ├── VirtualMachineScaleSetApiMockTest.java │ │ │ │ ├── VirtualNetworkApiLiveTest.java │ │ │ │ ├── VirtualNetworkApiMockTest.java │ │ │ │ ├── VirtualNetworkGatewayApiLiveTest.java │ │ │ │ ├── VirtualNetworkGatewayApiMockTest.java │ │ │ │ ├── VirtualNetworkGatewayConnectionApiLiveTest.java │ │ │ │ └── VirtualNetworkGatewayConnectionApiMockTest.java │ │ │ ├── filters/ │ │ │ │ └── ApiVersionFilterTest.java │ │ │ ├── functions/ │ │ │ │ └── URIParserTest.java │ │ │ ├── handlers/ │ │ │ │ └── AzureRetryableErrorHandlerTest.java │ │ │ └── internal/ │ │ │ ├── AzureLiveTestUtils.java │ │ │ ├── BaseAzureComputeApiLiveTest.java │ │ │ └── BaseAzureComputeApiMockTest.java │ │ └── resources/ │ │ ├── PublicIPAddressCreate.json │ │ ├── PublicIPAddressCreateDnsRecordInUse.json │ │ ├── PublicIPAddressGetInfo.json │ │ ├── PublicIPAddressList.json │ │ ├── PublicIPAddressListAll.json │ │ ├── activitylogalertcreate.json │ │ ├── activitylogalertget.json │ │ ├── activitylogalertresourcegroup.json │ │ ├── alertchangestate.json │ │ ├── alertgetall.json │ │ ├── alertgethistory.json │ │ ├── alertgetsummary.json │ │ ├── alertsgetbyid.json │ │ ├── availabilitysetcreate.json │ │ ├── availabilitysetget.json │ │ ├── availabilitysetlist.json │ │ ├── connectioncreate.json │ │ ├── connectionget.json │ │ ├── connectionlist.json │ │ ├── createdeploymentaccepted.json │ │ ├── createdeploymentsucceeded.json │ │ ├── creatediskresponse.json │ │ ├── creatediskwithtagsandskuresponse.json │ │ ├── creatediskwithtagsresponse.json │ │ ├── createnetworkinterfacecard.json │ │ ├── createsubnet.json │ │ ├── createsubnetresponse.json │ │ ├── createvirtualmachineresponse.json │ │ ├── createvirtualnetwork.json │ │ ├── getdisk.json │ │ ├── getnetworkinterfacecard.json │ │ ├── getonesubnet.json │ │ ├── getresourceprovidermetadata.json │ │ ├── getvault.json │ │ ├── image.json │ │ ├── ipnotavailable.json │ │ ├── isavailablestorageservice.json │ │ ├── listallnetworkinterfaces.json │ │ ├── listdeployments.json │ │ ├── listdisks.json │ │ ├── listnetworkinterfaces.json │ │ ├── listsubnetswithinvirtualnetwork.json │ │ ├── listvirtualnetworks.json │ │ ├── listvirtualnetworksall.json │ │ ├── loadbalancercreate.json │ │ ├── loadbalancerget.json │ │ ├── loadbalancerlist.json │ │ ├── loadbalancerlistall.json │ │ ├── localnetworkgatewaycreate.json │ │ ├── localnetworkgatewayget.json │ │ ├── localnetworkgatewaylist.json │ │ ├── locations.json │ │ ├── logback-test.xml │ │ ├── metricalertcreateorupdate.json │ │ ├── metricalertget.json │ │ ├── metricalertgetbyresource.json │ │ ├── metricdefinitions.json │ │ ├── metrics.json │ │ ├── networksecuritygroupcreate.json │ │ ├── networksecuritygroupget.json │ │ ├── networksecuritygrouplist.json │ │ ├── networksecuritygrouplistall.json │ │ ├── networksecurityrulecreate.json │ │ ├── networksecurityruleget.json │ │ ├── networksecurityrulegetdefault.json │ │ ├── networksecurityrulelist.json │ │ ├── networksecurityrulelistdefault.json │ │ ├── offers.json │ │ ├── publishers.json │ │ ├── resourceDefinition.json │ │ ├── resourcegroup-resources.json │ │ ├── resourcegroup.json │ │ ├── resourcegroups.json │ │ ├── resourcegroupupdated.json │ │ ├── serviceprincipals.json │ │ ├── skus.json │ │ ├── storageAccounts.json │ │ ├── storageCreateResponse.json │ │ ├── storageaccountkeys.json │ │ ├── storageaccountupdate.json │ │ ├── storageservices.json │ │ ├── vaultbackupkey.json │ │ ├── vaultbackupsecret.json │ │ ├── vaultcreate.json │ │ ├── vaultcreatecertificate.json │ │ ├── vaultcreatecertificaterequestbody.json │ │ ├── vaultcreatekey.json │ │ ├── vaultcreatekeyrequestbody.json │ │ ├── vaultcreaterequestbody.json │ │ ├── vaultdeletecertificate.json │ │ ├── vaultdeletecertificatecontacts.json │ │ ├── vaultdeletecertificateissuer.json │ │ ├── vaultdeletecertificateoperation.json │ │ ├── vaultdeletekey.json │ │ ├── vaultdeletesecret.json │ │ ├── vaultget.json │ │ ├── vaultgetcertificate.json │ │ ├── vaultgetcertificatecontacts.json │ │ ├── vaultgetcertificateissuer.json │ │ ├── vaultgetcertificateoperation.json │ │ ├── vaultgetcertificatepolicy.json │ │ ├── vaultgetdeleted.json │ │ ├── vaultgetdeletedcertificate.json │ │ ├── vaultgetdeletedkey.json │ │ ├── vaultgetdeletedsecret.json │ │ ├── vaultgetkey.json │ │ ├── vaultgetkeyversions.json │ │ ├── vaultgetsecret.json │ │ ├── vaultgetsecretversions.json │ │ ├── vaultimportablecert.txt │ │ ├── vaultimportcertificate.json │ │ ├── vaultimportcertificaterequestbody.json │ │ ├── vaultimportkeyrequestbody.json │ │ ├── vaultkeybackup.txt │ │ ├── vaultkeydecrypt.json │ │ ├── vaultkeydecryptrequestbody.json │ │ ├── vaultkeyencrypt.json │ │ ├── vaultkeyencryptrequestbody.json │ │ ├── vaultkeysign.json │ │ ├── vaultkeysignrequestbody.json │ │ ├── vaultkeyunwrap.json │ │ ├── vaultkeyunwraprequestbody.json │ │ ├── vaultkeyverify.json │ │ ├── vaultkeyverifyrequestbody.json │ │ ├── vaultkeywrap.json │ │ ├── vaultkeywraprequestbody.json │ │ ├── vaultlist.json │ │ ├── vaultlistcertificateissuers.json │ │ ├── vaultlistcertificates.json │ │ ├── vaultlistcertificateversions.json │ │ ├── vaultlistdeleted.json │ │ ├── vaultlistdeletedcertificates.json │ │ ├── vaultlistdeletedkeys.json │ │ ├── vaultlistdeletedsecrets.json │ │ ├── vaultlistkeys.json │ │ ├── vaultlistsecrets.json │ │ ├── vaultmergecertificate.json │ │ ├── vaultmergecertificaterequestbody.json │ │ ├── vaultmergex5c-1.txt │ │ ├── vaultmergex5c-2.txt │ │ ├── vaultmergex5c-3.txt │ │ ├── vaultrecoverdeletedcertificate.json │ │ ├── vaultrecoverdeletedkey.json │ │ ├── vaultrecoverdeletedsecret.json │ │ ├── vaultrestorekey.json │ │ ├── vaultrestorekeyrequestbody.json │ │ ├── vaultrestoresecret.json │ │ ├── vaultrestoresecretrequestbody.json │ │ ├── vaultsamplesecret.txt │ │ ├── vaultsecretbackup.txt │ │ ├── vaultsetcertificatecontacts.json │ │ ├── vaultsetcertificatecontactsrequestbody.json │ │ ├── vaultsetcertificateissuer.json │ │ ├── vaultsetcertificateissuerrequestbody.json │ │ ├── vaultsetsecret.json │ │ ├── vaultsetsecretrequestbody.json │ │ ├── vaultupdatecertificate.json │ │ ├── vaultupdatecertificateissuer.json │ │ ├── vaultupdatecertificateissuerrequestbody.json │ │ ├── vaultupdatecertificateoperation.json │ │ ├── vaultupdatecertificateoperationrequestbody.json │ │ ├── vaultupdatecertificatepolicy.json │ │ ├── vaultupdatecertificatepolicyrequestbody.json │ │ ├── vaultupdatecertificaterequestbody.json │ │ ├── vaultupdatekey.json │ │ ├── vaultupdatekeyrequestbody.json │ │ ├── vaultupdatekeywithversion.json │ │ ├── vaultupdatesecret.json │ │ ├── vaultupdatesecretrequestbody.json │ │ ├── vaultupdatesecretwithversion.json │ │ ├── vaultupdatesecretwithversionrequestbody.json │ │ ├── versions.json │ │ ├── virtualmachine.json │ │ ├── virtualmachineInstance.json │ │ ├── virtualmachineavailablesizes.json │ │ ├── virtualmachineimagecreate.json │ │ ├── virtualmachineimageget.json │ │ ├── virtualmachineimagelist.json │ │ ├── virtualmachinescalesetget.json │ │ ├── virtualmachinescalesetgetwhen404.json │ │ ├── virtualmachinescalesetlist.json │ │ ├── virtualmachinescalesetlistwhen404.json │ │ ├── virtualmachinescalesetresponsecreateorupdate.json │ │ ├── virtualmachinesinlocation.json │ │ ├── virtualmachinesinresourcegroup.json │ │ ├── virtualmachinesinsubscription.json │ │ ├── virtualnetwork.json │ │ ├── virtualnetworkgatewaycreate.json │ │ ├── virtualnetworkgatewayget.json │ │ ├── virtualnetworkgatewaylist.json │ │ └── vmsizes.json │ ├── b2/ │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── b2/ │ │ │ ├── B2Api.java │ │ │ ├── B2ApiMetadata.java │ │ │ ├── B2ProviderMetadata.java │ │ │ ├── B2ResponseException.java │ │ │ ├── binders/ │ │ │ │ ├── UploadFileBinder.java │ │ │ │ └── UploadPartBinder.java │ │ │ ├── blobstore/ │ │ │ │ ├── B2BlobStore.java │ │ │ │ └── config/ │ │ │ │ └── B2BlobStoreContextModule.java │ │ │ ├── config/ │ │ │ │ └── B2HttpApiModule.java │ │ │ ├── domain/ │ │ │ │ ├── Action.java │ │ │ │ ├── Authorization.java │ │ │ │ ├── B2Error.java │ │ │ │ ├── B2Object.java │ │ │ │ ├── B2ObjectList.java │ │ │ │ ├── Bucket.java │ │ │ │ ├── BucketList.java │ │ │ │ ├── BucketType.java │ │ │ │ ├── DeleteFileResponse.java │ │ │ │ ├── GetUploadPartResponse.java │ │ │ │ ├── HideFileResponse.java │ │ │ │ ├── ListPartsResponse.java │ │ │ │ ├── ListUnfinishedLargeFilesResponse.java │ │ │ │ ├── MultipartUploadResponse.java │ │ │ │ ├── UploadFileResponse.java │ │ │ │ ├── UploadPartResponse.java │ │ │ │ └── UploadUrlResponse.java │ │ │ ├── features/ │ │ │ │ ├── AuthorizationApi.java │ │ │ │ ├── BucketApi.java │ │ │ │ ├── MultipartApi.java │ │ │ │ └── ObjectApi.java │ │ │ ├── filters/ │ │ │ │ ├── B2RetryHandler.java │ │ │ │ ├── RequestAuthorization.java │ │ │ │ └── RequestAuthorizationDownload.java │ │ │ ├── functions/ │ │ │ │ └── ParseB2ObjectFromResponse.java │ │ │ ├── handlers/ │ │ │ │ └── ParseB2ErrorFromJsonContent.java │ │ │ └── reference/ │ │ │ └── B2Headers.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── b2/ │ │ │ ├── B2ProviderMetadataTest.java │ │ │ ├── blobstore/ │ │ │ │ └── integration/ │ │ │ │ ├── B2BlobIntegrationLiveTest.java │ │ │ │ ├── B2BlobLiveTest.java │ │ │ │ ├── B2BlobSignerLiveTest.java │ │ │ │ ├── B2ContainerIntegrationLiveTest.java │ │ │ │ └── B2ContainerLiveTest.java │ │ │ ├── features/ │ │ │ │ ├── B2TestUtils.java │ │ │ │ ├── BucketApiLiveTest.java │ │ │ │ ├── BucketApiMockTest.java │ │ │ │ ├── MultipartApiLiveTest.java │ │ │ │ ├── MultipartApiMockTest.java │ │ │ │ ├── ObjectApiLiveTest.java │ │ │ │ └── ObjectApiMockTest.java │ │ │ └── internal/ │ │ │ └── BaseB2ApiLiveTest.java │ │ └── resources/ │ │ ├── authorize_account_response.json │ │ ├── bucket.json │ │ ├── cancel_large_file_request.json │ │ ├── cancel_large_file_response.json │ │ ├── create_bucket_request.json │ │ ├── delete_bucket_already_deleted_response.json │ │ ├── delete_bucket_request.json │ │ ├── delete_file_version_already_deleted_response.json │ │ ├── delete_object_request.json │ │ ├── delete_object_response.json │ │ ├── finish_large_file_request.json │ │ ├── finish_large_file_response.json │ │ ├── get_file_info_deleted_file_response.json │ │ ├── get_file_info_request.json │ │ ├── get_file_info_response.json │ │ ├── get_upload_part_url_request.json │ │ ├── get_upload_part_url_response.json │ │ ├── get_upload_url_deleted_bucket_response.json │ │ ├── get_upload_url_request.json │ │ ├── get_upload_url_response.json │ │ ├── hide_file_request.json │ │ ├── hide_file_response.json │ │ ├── list_buckets_request.json │ │ ├── list_buckets_response.json │ │ ├── list_file_names_request.json │ │ ├── list_file_names_response.json │ │ ├── list_file_versions_request.json │ │ ├── list_file_versions_response.json │ │ ├── list_parts_request.json │ │ ├── list_parts_response.json │ │ ├── list_unfinished_large_files_request.json │ │ ├── list_unfinished_large_files_response.json │ │ ├── log4j.xml │ │ ├── start_large_file_request.json │ │ ├── start_large_file_response.json │ │ ├── update_bucket_request.json │ │ ├── upload_file_response.json │ │ └── upload_part_response.json │ ├── digitalocean2/ │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── digitalocean2/ │ │ │ ├── DigitalOcean2Api.java │ │ │ ├── DigitalOcean2ApiMetadata.java │ │ │ ├── DigitalOcean2ProviderMetadata.java │ │ │ ├── compute/ │ │ │ │ ├── DigitalOcean2ComputeServiceAdapter.java │ │ │ │ ├── config/ │ │ │ │ │ └── DigitalOcean2ComputeServiceContextModule.java │ │ │ │ ├── extensions/ │ │ │ │ │ └── DigitalOcean2ImageExtension.java │ │ │ │ ├── functions/ │ │ │ │ │ ├── DropletStatusToStatus.java │ │ │ │ │ ├── DropletToNodeMetadata.java │ │ │ │ │ ├── ImageInRegionToImage.java │ │ │ │ │ ├── RegionToLocation.java │ │ │ │ │ └── SizeToHardware.java │ │ │ │ ├── internal/ │ │ │ │ │ └── ImageInRegion.java │ │ │ │ ├── options/ │ │ │ │ │ └── DigitalOcean2TemplateOptions.java │ │ │ │ └── strategy/ │ │ │ │ └── CreateKeyPairsThenCreateNodes.java │ │ │ ├── config/ │ │ │ │ ├── DigitalOcean2HttpApiModule.java │ │ │ │ ├── DigitalOcean2RateLimitModule.java │ │ │ │ └── DigitalOceanParserModule.java │ │ │ ├── domain/ │ │ │ │ ├── Action.java │ │ │ │ ├── Backup.java │ │ │ │ ├── Distribution.java │ │ │ │ ├── Droplet.java │ │ │ │ ├── DropletCreate.java │ │ │ │ ├── Image.java │ │ │ │ ├── Kernel.java │ │ │ │ ├── Key.java │ │ │ │ ├── Networks.java │ │ │ │ ├── OperatingSystem.java │ │ │ │ ├── Region.java │ │ │ │ ├── Size.java │ │ │ │ ├── Snapshot.java │ │ │ │ ├── internal/ │ │ │ │ │ └── PaginatedCollection.java │ │ │ │ └── options/ │ │ │ │ ├── CreateDropletOptions.java │ │ │ │ ├── ImageListOptions.java │ │ │ │ └── ListOptions.java │ │ │ ├── exceptions/ │ │ │ │ └── DigitalOcean2RateLimitExceededException.java │ │ │ ├── features/ │ │ │ │ ├── ActionApi.java │ │ │ │ ├── DropletApi.java │ │ │ │ ├── ImageApi.java │ │ │ │ ├── KeyApi.java │ │ │ │ ├── RegionApi.java │ │ │ │ └── SizeApi.java │ │ │ ├── functions/ │ │ │ │ ├── BaseToPagedIterable.java │ │ │ │ ├── LinkToImageListOptions.java │ │ │ │ └── LinkToListOptions.java │ │ │ ├── handlers/ │ │ │ │ ├── DigitalOcean2ErrorHandler.java │ │ │ │ └── DigitalOcean2RateLimitRetryHandler.java │ │ │ └── ssh/ │ │ │ ├── DSAKeys.java │ │ │ └── ECDSAKeys.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── digitalocean2/ │ │ │ ├── DigitalOcean2ProviderMetadataTest.java │ │ │ ├── compute/ │ │ │ │ ├── DigitalOcean2ComputeServiceLiveTest.java │ │ │ │ ├── DigitalOcean2TemplateBuilderLiveTest.java │ │ │ │ ├── config/ │ │ │ │ │ ├── ActionDonePredicateTest.java │ │ │ │ │ ├── DropletInStatusPredicateTest.java │ │ │ │ │ └── DropletTerminatedPredicateTest.java │ │ │ │ ├── extensions/ │ │ │ │ │ └── DigitalOcean2ImageExtensionLiveTest.java │ │ │ │ ├── functions/ │ │ │ │ │ ├── DropletStatusToStatusTest.java │ │ │ │ │ ├── DropletToNodeMetadataTest.java │ │ │ │ │ ├── ImageInRegionToImageTest.java │ │ │ │ │ ├── RegionToLocationTest.java │ │ │ │ │ └── SizeToHardwareTest.java │ │ │ │ └── options/ │ │ │ │ └── DigitalOcean2TemplateOptionsTest.java │ │ │ ├── domain/ │ │ │ │ └── OperatingSystemTest.java │ │ │ ├── exceptions/ │ │ │ │ └── RateLimitExceptionMockTest.java │ │ │ ├── features/ │ │ │ │ ├── ActionApiLiveTest.java │ │ │ │ ├── ActionApiMockTest.java │ │ │ │ ├── DropletApiLiveTest.java │ │ │ │ ├── DropletApiMockTest.java │ │ │ │ ├── ImageApiLiveTest.java │ │ │ │ ├── ImageApiMockTest.java │ │ │ │ ├── KeyApiLiveTest.java │ │ │ │ ├── KeyApiMockTest.java │ │ │ │ ├── RegionApiLiveTest.java │ │ │ │ ├── RegionApiMockTest.java │ │ │ │ ├── SizeApiLiveTest.java │ │ │ │ └── SizeApiMockTest.java │ │ │ ├── functions/ │ │ │ │ ├── LinkToImageListOptionsTest.java │ │ │ │ └── LinkToListOptionsTest.java │ │ │ ├── internal/ │ │ │ │ ├── BaseDigitalOcean2ApiLiveTest.java │ │ │ │ └── BaseDigitalOcean2ApiMockTest.java │ │ │ └── ssh/ │ │ │ ├── DSAKeysTest.java │ │ │ └── ECDSAKeysTest.java │ │ └── resources/ │ │ ├── action.json │ │ ├── actions-first.json │ │ ├── actions-last.json │ │ ├── backups-first.json │ │ ├── backups-last.json │ │ ├── droplet-create-req.json │ │ ├── droplet-create-res.json │ │ ├── droplet.json │ │ ├── droplets-first.json │ │ ├── droplets-last.json │ │ ├── image.json │ │ ├── images-first.json │ │ ├── images-last.json │ │ ├── kernels-first.json │ │ ├── kernels-last.json │ │ ├── key.json │ │ ├── keys-first.json │ │ ├── keys-last.json │ │ ├── logback-test.xml │ │ ├── power-cycle.json │ │ ├── power-off.json │ │ ├── power-on.json │ │ ├── reboot.json │ │ ├── regions-first.json │ │ ├── regions-last.json │ │ ├── shutdown.json │ │ ├── sizes-first.json │ │ ├── sizes-last.json │ │ ├── snapshot.json │ │ ├── snapshots-first.json │ │ ├── snapshots-last.json │ │ ├── ssh-dsa.pub │ │ ├── ssh-ecdsa.pub │ │ └── token.json │ ├── dynect/ │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── dynect/ │ │ │ └── v3/ │ │ │ ├── DynECTApi.java │ │ │ ├── DynECTApiMetadata.java │ │ │ ├── DynECTExceptions.java │ │ │ ├── DynECTFallbacks.java │ │ │ ├── DynECTProviderMetadata.java │ │ │ ├── binders/ │ │ │ │ ├── CreateRecordBinder.java │ │ │ │ └── RecordIdBinder.java │ │ │ ├── config/ │ │ │ │ ├── DynECTHttpApiModule.java │ │ │ │ └── DynECTParserModule.java │ │ │ ├── domain/ │ │ │ │ ├── CreatePrimaryZone.java │ │ │ │ ├── CreateRecord.java │ │ │ │ ├── GeoRegionGroup.java │ │ │ │ ├── GeoService.java │ │ │ │ ├── Job.java │ │ │ │ ├── Node.java │ │ │ │ ├── Record.java │ │ │ │ ├── RecordId.java │ │ │ │ ├── RecordSet.java │ │ │ │ ├── SOARecord.java │ │ │ │ ├── Session.java │ │ │ │ ├── SessionCredentials.java │ │ │ │ ├── Zone.java │ │ │ │ └── rdata/ │ │ │ │ ├── AAAAData.java │ │ │ │ ├── AData.java │ │ │ │ ├── CNAMEData.java │ │ │ │ ├── MXData.java │ │ │ │ ├── NSData.java │ │ │ │ ├── PTRData.java │ │ │ │ ├── SOAData.java │ │ │ │ ├── SPFData.java │ │ │ │ ├── SRVData.java │ │ │ │ ├── SSHFPData.java │ │ │ │ └── TXTData.java │ │ │ ├── features/ │ │ │ │ ├── GeoRegionGroupApi.java │ │ │ │ ├── GeoServiceApi.java │ │ │ │ ├── RecordApi.java │ │ │ │ ├── SessionApi.java │ │ │ │ └── ZoneApi.java │ │ │ ├── filters/ │ │ │ │ ├── AlwaysAddContentType.java │ │ │ │ └── SessionManager.java │ │ │ ├── functions/ │ │ │ │ ├── ExtractLastPathComponent.java │ │ │ │ └── ToRecordIds.java │ │ │ ├── handlers/ │ │ │ │ ├── DynECTErrorHandler.java │ │ │ │ └── GetJobRedirectionRetryHandler.java │ │ │ ├── loaders/ │ │ │ │ └── LoginUserInOrgWithPassword.java │ │ │ └── predicates/ │ │ │ └── RecordPredicates.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── dynect/ │ │ │ └── v3/ │ │ │ ├── DynECTProviderMetadataTest.java │ │ │ ├── DynectApiMockTest.java │ │ │ ├── features/ │ │ │ │ ├── GeoRegionGroupApiExpectTest.java │ │ │ │ ├── GeoRegionGroupApiLiveTest.java │ │ │ │ ├── GeoServiceApiExpectTest.java │ │ │ │ ├── GeoServiceApiLiveTest.java │ │ │ │ ├── RecordApiExpectTest.java │ │ │ │ ├── RecordApiLiveTest.java │ │ │ │ ├── SessionApiExpectTest.java │ │ │ │ ├── SessionApiLiveTest.java │ │ │ │ ├── ZoneApiExpectTest.java │ │ │ │ └── ZoneApiLiveTest.java │ │ │ ├── filters/ │ │ │ │ └── SessionManagerTest.java │ │ │ ├── functions/ │ │ │ │ ├── ExtractLastPathComponentTest.java │ │ │ │ └── ToRecordIdsTest.java │ │ │ ├── handlers/ │ │ │ │ └── GetJobRedirectionRetryHandlerExpectTest.java │ │ │ ├── internal/ │ │ │ │ ├── BaseDynECTApiExpectTest.java │ │ │ │ ├── BaseDynECTApiLiveTest.java │ │ │ │ ├── BaseDynECTExpectTest.java │ │ │ │ └── BaseDynECTParseTest.java │ │ │ ├── parse/ │ │ │ │ ├── CreateSessionResponseTest.java │ │ │ │ ├── DeleteZoneChangesResponseTest.java │ │ │ │ ├── DeleteZoneResponseTest.java │ │ │ │ ├── GetAAAARecordResponseTest.java │ │ │ │ ├── GetARecordResponseTest.java │ │ │ │ ├── GetCNAMERecordResponseTest.java │ │ │ │ ├── GetGeoRegionGroupResponseTest.java │ │ │ │ ├── GetGeoServiceResponseTest.java │ │ │ │ ├── GetMXRecordResponseTest.java │ │ │ │ ├── GetNSRecordResponseTest.java │ │ │ │ ├── GetPTRRecordResponseTest.java │ │ │ │ ├── GetRecordResponseTest.java │ │ │ │ ├── GetSOARecordResponseTest.java │ │ │ │ ├── GetSPFRecordResponseTest.java │ │ │ │ ├── GetSRVRecordResponseTest.java │ │ │ │ ├── GetSSHFPRecordResponseTest.java │ │ │ │ ├── GetTXTRecordResponseTest.java │ │ │ │ ├── GetZoneResponseTest.java │ │ │ │ ├── ListGeoRegionGroupsResponseTest.java │ │ │ │ ├── ListGeoServicesResponseTest.java │ │ │ │ ├── ListRecordsResponseTest.java │ │ │ │ └── ListZonesResponseTest.java │ │ │ └── predicates/ │ │ │ └── RecordPredicatesTest.java │ │ └── resources/ │ │ ├── create_session.json │ │ ├── delete_record.json │ │ ├── delete_zone.json │ │ ├── delete_zone_changes.json │ │ ├── get_geo_regiongroup.json │ │ ├── get_geo_service.json │ │ ├── get_record_a.json │ │ ├── get_record_aaaa.json │ │ ├── get_record_cname.json │ │ ├── get_record_mx.json │ │ ├── get_record_ns.json │ │ ├── get_record_ptr.json │ │ ├── get_record_soa.json │ │ ├── get_record_spf.json │ │ ├── get_record_srv.json │ │ ├── get_record_sshfp.json │ │ ├── get_record_txt.json │ │ ├── get_zone.json │ │ ├── ip_mismatch.json │ │ ├── list_geo_regiongroups.json │ │ ├── list_geo_services.json │ │ ├── list_records.json │ │ ├── list_zones.json │ │ ├── logback.xml │ │ ├── logout.json │ │ ├── new_record.json │ │ ├── new_zone.json │ │ ├── session_invalid.json │ │ └── session_valid.json │ ├── elastichosts-ams-e/ │ │ ├── README.txt │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── elastichosts/ │ │ │ └── ElasticHostsAmsterdamMetadata.java │ │ └── test/ │ │ └── java/ │ │ └── org/ │ │ └── jclouds/ │ │ └── elastichosts/ │ │ ├── ElasticHostsAmsterdamApiLiveTest.java │ │ ├── ElasticHostsAmsterdamProviderTest.java │ │ └── compute/ │ │ ├── ElasticHostsAmsterdamComputeServiceLiveTest.java │ │ └── ElasticHostsAmsterdamTemplateBuilderLiveTest.java │ ├── elastichosts-dal-a/ │ │ ├── README.txt │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── elastichosts/ │ │ │ └── ElasticHostsDallasMetadata.java │ │ └── test/ │ │ └── java/ │ │ └── org/ │ │ └── jclouds/ │ │ └── elastichosts/ │ │ ├── ElasticHostsDallasApiLiveTest.java │ │ ├── ElasticHostsDallasProviderTest.java │ │ └── compute/ │ │ ├── ElasticHostsDallasComputeServiceLiveTest.java │ │ └── ElasticHostsDallasTemplateBuilderLiveTest.java │ ├── elastichosts-hkg-e/ │ │ ├── README.txt │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── elastichosts/ │ │ │ └── ElasticHostsHongKongProviderMetadata.java │ │ └── test/ │ │ └── java/ │ │ └── org/ │ │ └── jclouds/ │ │ └── elastichosts/ │ │ ├── ElasticHostsHongKongApiLiveTest.java │ │ ├── ElasticHostsHongKongProviderTest.java │ │ └── compute/ │ │ ├── ElasticHostsHongKongComputeServiceLiveTest.java │ │ └── ElasticHostsHongKongTemplateBuilderLiveTest.java │ ├── elastichosts-lax-p/ │ │ ├── README.txt │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── elastichosts/ │ │ │ └── ElasticHostsPeer1LosAngelesProviderMetadata.java │ │ └── test/ │ │ └── java/ │ │ └── org/ │ │ └── jclouds/ │ │ └── elastichosts/ │ │ ├── ElasticHostsPeer1LosAngelesApiLiveTest.java │ │ ├── ElasticHostsPeer1LosAngelesProviderTest.java │ │ └── compute/ │ │ ├── ElasticHostsPeer1LosAngelesComputeServiceLiveTest.java │ │ └── ElasticHostsPeer1LosAngelesTemplateBuilderLiveTest.java │ ├── elastichosts-lon-b/ │ │ ├── README.txt │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── elastichosts/ │ │ │ └── ElasticHostsBlueSquareLondonProviderMetadata.java │ │ └── test/ │ │ └── java/ │ │ └── org/ │ │ └── jclouds/ │ │ └── elastichosts/ │ │ ├── ElasticHostsBlueSquareLondonApiLiveTest.java │ │ ├── ElasticHostsBlueSquareLondonProviderTest.java │ │ └── compute/ │ │ ├── ElasticHostsBlueSquareLondonComputeServiceLiveTest.java │ │ └── ElasticHostsBlueSquareLondonTemplateBuilderLiveTest.java │ ├── elastichosts-lon-p/ │ │ ├── README.txt │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── elastichosts/ │ │ │ └── ElasticHostsPeer1LondonProviderMetadata.java │ │ └── test/ │ │ └── java/ │ │ └── org/ │ │ └── jclouds/ │ │ └── elastichosts/ │ │ ├── ElasticHostsPeer1LondonApiLiveTest.java │ │ ├── ElasticHostsPeer1LondonProviderTest.java │ │ └── compute/ │ │ ├── ElasticHostsPeer1LondonComputeServiceLiveTest.java │ │ └── ElasticHostsPeer1LondonTemplateBuilderLiveTest.java │ ├── elastichosts-mmi-a/ │ │ ├── README.txt │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── elastichosts/ │ │ │ └── ElasticHostsMiamiMetadata.java │ │ └── test/ │ │ └── java/ │ │ └── org/ │ │ └── jclouds/ │ │ └── elastichosts/ │ │ ├── ElasticHostsMiamiApiLiveTest.java │ │ ├── ElasticHostsMiamiProviderTest.java │ │ └── compute/ │ │ ├── ElasticHostsMiamiComputeServiceLiveTest.java │ │ └── ElasticHostsMiamiTemplateBuilderLiveTest.java │ ├── elastichosts-sat-p/ │ │ ├── README.txt │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── elastichosts/ │ │ │ └── ElasticHostsPeer1SanAntonioProviderMetadata.java │ │ └── test/ │ │ └── java/ │ │ └── org/ │ │ └── jclouds/ │ │ └── elastichosts/ │ │ ├── ElasticHostsPeer1SanAntonioApiLiveTest.java │ │ ├── ElasticHostsPeer1SanAntonioProviderTest.java │ │ └── compute/ │ │ ├── ElasticHostsPeer1SanAntonioComputeServiceLiveTest.java │ │ └── ElasticHostsPeer1SanAntonioTemplateBuilderLiveTest.java │ ├── elastichosts-sjc-c/ │ │ ├── README.txt │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── elastichosts/ │ │ │ └── ElasticHostsSanJoseProviderMetadata.java │ │ └── test/ │ │ └── java/ │ │ └── org/ │ │ └── jclouds/ │ │ └── elastichosts/ │ │ ├── ElasticHostsSanJoseApiLiveTest.java │ │ ├── ElasticHostsSanJoseProviderTest.java │ │ └── compute/ │ │ ├── ElasticHostsSanJoseComputeServiceLiveTest.java │ │ └── ElasticHostsSanJoseTemplateBuilderLiveTest.java │ ├── elastichosts-syd-v/ │ │ ├── README.txt │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── elastichosts/ │ │ │ └── ElasticHostsSydneyProviderMetadata.java │ │ └── test/ │ │ └── java/ │ │ └── org/ │ │ └── jclouds/ │ │ └── elastichosts/ │ │ ├── ElasticHostsSydneyApiLiveTest.java │ │ ├── ElasticHostsSydneyProviderTest.java │ │ └── compute/ │ │ ├── ElasticHostsSydneyComputeServiceLiveTest.java │ │ └── ElasticHostsSydneyTemplateBuilderLiveTest.java │ ├── elastichosts-tor-p/ │ │ ├── README.txt │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── elastichosts/ │ │ │ └── ElasticHostsPeer1TorontoProviderMetadata.java │ │ └── test/ │ │ └── java/ │ │ └── org/ │ │ └── jclouds/ │ │ └── elastichosts/ │ │ ├── ElasticHostsPeer1TorontoApiLiveTest.java │ │ ├── ElasticHostsPeer1TorontoProviderTest.java │ │ └── compute/ │ │ ├── ElasticHostsPeer1TorontoComputeServiceLiveTest.java │ │ └── ElasticHostsPeer1TorontoTemplateBuilderLiveTest.java │ ├── glesys/ │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── glesys/ │ │ │ ├── GleSYSApi.java │ │ │ ├── GleSYSApiMetadata.java │ │ │ ├── GleSYSProviderMetadata.java │ │ │ ├── compute/ │ │ │ │ ├── GleSYSComputeServiceAdapter.java │ │ │ │ ├── config/ │ │ │ │ │ └── GleSYSComputeServiceContextModule.java │ │ │ │ ├── functions/ │ │ │ │ │ ├── DatacenterToLocation.java │ │ │ │ │ ├── OSTemplateToImage.java │ │ │ │ │ ├── ParseOsFamilyVersion64BitFromImageName.java │ │ │ │ │ ├── ServerDetailsToNodeMetadata.java │ │ │ │ │ └── ServerSpecToHardware.java │ │ │ │ └── options/ │ │ │ │ └── GleSYSTemplateOptions.java │ │ │ ├── config/ │ │ │ │ ├── GleSYSHttpApiModule.java │ │ │ │ └── GleSYSParserModule.java │ │ │ ├── domain/ │ │ │ │ ├── AllowedArguments.java │ │ │ │ ├── AllowedArgumentsForCreateServer.java │ │ │ │ ├── Archive.java │ │ │ │ ├── ArchiveAllowedArguments.java │ │ │ │ ├── Console.java │ │ │ │ ├── Cost.java │ │ │ │ ├── Domain.java │ │ │ │ ├── DomainRecord.java │ │ │ │ ├── EmailAccount.java │ │ │ │ ├── EmailAlias.java │ │ │ │ ├── EmailOverview.java │ │ │ │ ├── EmailOverviewDomain.java │ │ │ │ ├── EmailOverviewSummary.java │ │ │ │ ├── EmailQuota.java │ │ │ │ ├── GleSYSBoolean.java │ │ │ │ ├── Ip.java │ │ │ │ ├── IpDetails.java │ │ │ │ ├── OSTemplate.java │ │ │ │ ├── ResourceStatus.java │ │ │ │ ├── ResourceUsage.java │ │ │ │ ├── ResourceUsageInfo.java │ │ │ │ ├── ResourceUsageValue.java │ │ │ │ ├── Server.java │ │ │ │ ├── ServerDetails.java │ │ │ │ ├── ServerLimit.java │ │ │ │ ├── ServerSpec.java │ │ │ │ ├── ServerStatus.java │ │ │ │ └── ServerUptime.java │ │ │ ├── features/ │ │ │ │ ├── ArchiveApi.java │ │ │ │ ├── DomainApi.java │ │ │ │ ├── EmailAccountApi.java │ │ │ │ ├── IpApi.java │ │ │ │ └── ServerApi.java │ │ │ ├── functions/ │ │ │ │ ├── ParseTemplatesFromHttpResponse.java │ │ │ │ └── internal/ │ │ │ │ └── GleSYSTypeAdapters.java │ │ │ ├── handlers/ │ │ │ │ └── GleSYSErrorHandler.java │ │ │ ├── options/ │ │ │ │ ├── AddDomainOptions.java │ │ │ │ ├── AddRecordOptions.java │ │ │ │ ├── CloneServerOptions.java │ │ │ │ ├── CreateAccountOptions.java │ │ │ │ ├── CreateServerOptions.java │ │ │ │ ├── DestroyServerOptions.java │ │ │ │ ├── DomainOptions.java │ │ │ │ ├── ListIpOptions.java │ │ │ │ ├── ServerStatusOptions.java │ │ │ │ ├── UpdateAccountOptions.java │ │ │ │ ├── UpdateRecordOptions.java │ │ │ │ └── UpdateServerOptions.java │ │ │ └── reference/ │ │ │ └── GleSYSConstants.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── glesys/ │ │ │ ├── GleSYSApiTest.java │ │ │ ├── GleSYSErrorHandlerTest.java │ │ │ ├── GleSYSProviderTest.java │ │ │ ├── compute/ │ │ │ │ ├── GleSYSComputeServiceAdapterExpectTest.java │ │ │ │ ├── GleSYSComputeServiceLiveTest.java │ │ │ │ ├── GleSYSExperimentExpectTest.java │ │ │ │ ├── GleSYSExperimentLiveTest.java │ │ │ │ ├── GleSYSTemplateBuilderLiveTest.java │ │ │ │ ├── functions/ │ │ │ │ │ ├── ParseOsFamilyVersion64BitFromImageNameTest.java │ │ │ │ │ ├── ServerDetailsToNodeMetadataTest.java │ │ │ │ │ └── ServerSpecToHardwareTest.java │ │ │ │ ├── internal/ │ │ │ │ │ └── BaseGleSYSComputeServiceExpectTest.java │ │ │ │ └── options/ │ │ │ │ └── GleSYSTemplateOptionsTest.java │ │ │ ├── features/ │ │ │ │ ├── ArchiveApiExpectTest.java │ │ │ │ ├── ArchiveApiLiveTest.java │ │ │ │ ├── DomainApiExpectTest.java │ │ │ │ ├── DomainApiLiveTest.java │ │ │ │ ├── EmailAccountApiExpectTest.java │ │ │ │ ├── EmailAccountApiLiveTest.java │ │ │ │ ├── IpApiExpectTest.java │ │ │ │ ├── IpApiLiveTest.java │ │ │ │ ├── ServerApiExpectTest.java │ │ │ │ └── ServerApiLiveTest.java │ │ │ ├── internal/ │ │ │ │ ├── BaseGleSYSApiExpectTest.java │ │ │ │ ├── BaseGleSYSApiLiveTest.java │ │ │ │ └── BaseGleSYSApiWithAServerLiveTest.java │ │ │ └── parse/ │ │ │ ├── ParseFullIpDetailsTest.java │ │ │ └── ParseIpAddressFromResponseTest.java │ │ └── resources/ │ │ ├── archive_allowed_arguments.json │ │ ├── archive_details.json │ │ ├── archive_list.json │ │ ├── domain_details.json │ │ ├── domain_list.json │ │ ├── domain_list_records.json │ │ ├── domain_record.json │ │ ├── email_details.json │ │ ├── email_list.json │ │ ├── email_overview.json │ │ ├── ip_get_details.json │ │ ├── ip_get_details_xen.json │ │ ├── ip_list_free.json │ │ ├── ip_list_own.json │ │ ├── ip_release.json │ │ ├── ip_take.json │ │ ├── log4j.xml │ │ ├── osmatches.json │ │ ├── server_allowed_arguments.json │ │ ├── server_console.json │ │ ├── server_details.json │ │ ├── server_limits.json │ │ ├── server_list.json │ │ ├── server_noip.json │ │ ├── server_resource_usage.json │ │ ├── server_status.json │ │ └── server_templates.json │ ├── go2cloud-jhb1/ │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── go2cloud/ │ │ │ └── Go2CloudJohannesburg1ProviderMetadata.java │ │ └── test/ │ │ └── java/ │ │ └── org/ │ │ └── jclouds/ │ │ └── go2cloud/ │ │ ├── Go2CloudJohannesburg1ApiLiveTest.java │ │ ├── Go2CloudJohannesburg1ProviderTest.java │ │ └── compute/ │ │ ├── Go2CloudJohannesburg1ComputeServiceLiveTest.java │ │ └── Go2CloudJohannesburg1TemplateBuilderLiveTest.java │ ├── gogrid/ │ │ ├── README.txt │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── gogrid/ │ │ │ ├── GoGridApi.java │ │ │ ├── GoGridApiMetadata.java │ │ │ ├── GoGridProviderMetadata.java │ │ │ ├── GoGridResponseException.java │ │ │ ├── binders/ │ │ │ │ ├── BindIdsToQueryParams.java │ │ │ │ ├── BindNamesToQueryParams.java │ │ │ │ ├── BindObjectNameToGetJobsRequestQueryParams.java │ │ │ │ ├── BindRealIpPortPairsToQueryParams.java │ │ │ │ └── BindVirtualIpPortPairToQueryParams.java │ │ │ ├── compute/ │ │ │ │ ├── GoGridComputeService.java │ │ │ │ ├── config/ │ │ │ │ │ └── GoGridComputeServiceContextModule.java │ │ │ │ ├── functions/ │ │ │ │ │ ├── OptionToLocation.java │ │ │ │ │ ├── ServerImageToImage.java │ │ │ │ │ └── ServerToNodeMetadata.java │ │ │ │ ├── options/ │ │ │ │ │ └── GoGridTemplateOptions.java │ │ │ │ ├── strategy/ │ │ │ │ │ └── GoGridComputeServiceAdapter.java │ │ │ │ └── suppliers/ │ │ │ │ └── GoGridHardwareSupplier.java │ │ │ ├── config/ │ │ │ │ ├── GoGridHttpApiModule.java │ │ │ │ └── GoGridParserModule.java │ │ │ ├── domain/ │ │ │ │ ├── BillingToken.java │ │ │ │ ├── Customer.java │ │ │ │ ├── Ip.java │ │ │ │ ├── IpPortPair.java │ │ │ │ ├── IpState.java │ │ │ │ ├── IpType.java │ │ │ │ ├── Job.java │ │ │ │ ├── JobProperties.java │ │ │ │ ├── JobState.java │ │ │ │ ├── LoadBalancer.java │ │ │ │ ├── LoadBalancerOs.java │ │ │ │ ├── LoadBalancerPersistenceType.java │ │ │ │ ├── LoadBalancerState.java │ │ │ │ ├── LoadBalancerType.java │ │ │ │ ├── ObjectType.java │ │ │ │ ├── Option.java │ │ │ │ ├── PowerCommand.java │ │ │ │ ├── Server.java │ │ │ │ ├── ServerImage.java │ │ │ │ ├── ServerImageState.java │ │ │ │ ├── ServerImageType.java │ │ │ │ ├── ServerState.java │ │ │ │ └── internal/ │ │ │ │ └── ErrorResponse.java │ │ │ ├── features/ │ │ │ │ ├── GridImageApi.java │ │ │ │ ├── GridIpApi.java │ │ │ │ ├── GridJobApi.java │ │ │ │ ├── GridLoadBalancerApi.java │ │ │ │ └── GridServerApi.java │ │ │ ├── filters/ │ │ │ │ └── SharedKeyLiteAuthentication.java │ │ │ ├── functions/ │ │ │ │ ├── GenericResponseContainer.java │ │ │ │ ├── ParseCredentialsFromJsonResponse.java │ │ │ │ ├── ParseImageFromJsonResponse.java │ │ │ │ ├── ParseImageListFromJsonResponse.java │ │ │ │ ├── ParseIpListFromJsonResponse.java │ │ │ │ ├── ParseJobListFromJsonResponse.java │ │ │ │ ├── ParseLoadBalancerFromJsonResponse.java │ │ │ │ ├── ParseLoadBalancerListFromJsonResponse.java │ │ │ │ ├── ParseOptionsFromJsonResponse.java │ │ │ │ ├── ParseServerNameToCredentialsMapFromJsonResponse.java │ │ │ │ └── internal/ │ │ │ │ └── CustomDeserializers.java │ │ │ ├── handlers/ │ │ │ │ └── GoGridErrorHandler.java │ │ │ ├── location/ │ │ │ │ └── GoGridDefaultLocationSupplier.java │ │ │ ├── options/ │ │ │ │ ├── AddLoadBalancerOptions.java │ │ │ │ ├── AddServerOptions.java │ │ │ │ ├── GetImageListOptions.java │ │ │ │ ├── GetIpListOptions.java │ │ │ │ ├── GetJobListOptions.java │ │ │ │ ├── GetServerListOptions.java │ │ │ │ └── SaveImageOptions.java │ │ │ ├── predicates/ │ │ │ │ ├── LoadBalancerLatestJobCompleted.java │ │ │ │ └── ServerLatestJobCompleted.java │ │ │ └── reference/ │ │ │ ├── GoGridHeaders.java │ │ │ └── GoGridQueryParams.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── gogrid/ │ │ │ ├── GoGridApiTest.java │ │ │ ├── GoGridLiveTestDisabled.java │ │ │ ├── GoGridProviderTest.java │ │ │ ├── binders/ │ │ │ │ ├── BindIdsToQueryParamsTest.java │ │ │ │ └── BindNamesToQueryParamsTest.java │ │ │ ├── compute/ │ │ │ │ ├── GoGridComputeServiceLiveTest.java │ │ │ │ ├── GoGridTemplateBuilderLiveTest.java │ │ │ │ ├── config/ │ │ │ │ │ └── GoGridComputeServiceContextModuleTest.java │ │ │ │ ├── functions/ │ │ │ │ │ └── ServerToNodeMetadataTest.java │ │ │ │ └── options/ │ │ │ │ └── GoGridTemplateOptionsTest.java │ │ │ ├── features/ │ │ │ │ ├── BaseGoGridApiLiveTest.java │ │ │ │ ├── BaseGoGridApiTest.java │ │ │ │ ├── BaseGoGridHttpApiExpectTest.java │ │ │ │ ├── GridImageApiLiveTest.java │ │ │ │ ├── GridImageApiTest.java │ │ │ │ ├── GridIpApiTest.java │ │ │ │ ├── GridJobApiLiveTest.java │ │ │ │ ├── GridJobApiTest.java │ │ │ │ ├── GridLoadBalancerApiTest.java │ │ │ │ ├── GridServerApiTest.java │ │ │ │ └── GridServerClientExpectTest.java │ │ │ ├── functions/ │ │ │ │ ├── ParseCredentialsFromJsonResponseTest.java │ │ │ │ ├── ParseJobsFromJsonResponseTest.java │ │ │ │ ├── ParseLoadBalancersFromJsonResponseTest.java │ │ │ │ └── ParseServerNameToCredentialsMapFromJsonResponseTest.java │ │ │ ├── handlers/ │ │ │ │ └── GoGridErrorHandlerTest.java │ │ │ ├── options/ │ │ │ │ ├── AddServerOptionsTest.java │ │ │ │ └── SaveImageOptionsTest.java │ │ │ ├── parse/ │ │ │ │ ├── ParseServerListTest.java │ │ │ │ └── ParseServerTest.java │ │ │ └── predicates/ │ │ │ └── ServerLatestJobCompletedTest.java │ │ └── resources/ │ │ ├── log4j.xml │ │ ├── test_credential.json │ │ ├── test_credentials_list.json │ │ ├── test_error_handler.json │ │ ├── test_get_job_list.json │ │ ├── test_get_load_balancer_list.json │ │ └── test_get_server_list.json │ ├── google-cloud-storage/ │ │ ├── README.md │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── googlecloudstorage/ │ │ │ ├── GoogleCloudStorageApi.java │ │ │ ├── GoogleCloudStorageApiMetadata.java │ │ │ ├── GoogleCloudStorageFallbacks.java │ │ │ ├── GoogleCloudStorageProviderMetadata.java │ │ │ ├── binders/ │ │ │ │ ├── MultipartUploadBinder.java │ │ │ │ └── UploadBinder.java │ │ │ ├── blobstore/ │ │ │ │ ├── GoogleCloudStorageBlobRequestSigner.java │ │ │ │ ├── GoogleCloudStorageBlobStore.java │ │ │ │ ├── config/ │ │ │ │ │ └── GoogleCloudStorageBlobStoreContextModule.java │ │ │ │ └── functions/ │ │ │ │ ├── BlobMetadataToObjectTemplate.java │ │ │ │ ├── BlobStoreListContainerOptionsToListObjectOptions.java │ │ │ │ ├── BucketToStorageMetadata.java │ │ │ │ ├── ObjectListToStorageMetadata.java │ │ │ │ └── ObjectToBlobMetadata.java │ │ │ ├── config/ │ │ │ │ ├── GoogleCloudStorageHttpApiModule.java │ │ │ │ ├── GoogleCloudStorageOAuthScopes.java │ │ │ │ └── GoogleCloudStorageParserModule.java │ │ │ ├── domain/ │ │ │ │ ├── Bucket.java │ │ │ │ ├── BucketAccessControls.java │ │ │ │ ├── DomainResourceReferences.java │ │ │ │ ├── GoogleCloudStorageObject.java │ │ │ │ ├── ListPageWithPrefixes.java │ │ │ │ ├── ObjectAccessControls.java │ │ │ │ ├── Owner.java │ │ │ │ ├── ProjectTeam.java │ │ │ │ ├── ResumableUpload.java │ │ │ │ ├── RewriteResponse.java │ │ │ │ └── templates/ │ │ │ │ ├── BucketAccessControlsTemplate.java │ │ │ │ ├── BucketTemplate.java │ │ │ │ ├── ComposeObjectTemplate.java │ │ │ │ ├── ObjectAccessControlsTemplate.java │ │ │ │ └── ObjectTemplate.java │ │ │ ├── features/ │ │ │ │ ├── BucketAccessControlsApi.java │ │ │ │ ├── BucketApi.java │ │ │ │ ├── DefaultObjectAccessControlsApi.java │ │ │ │ ├── ObjectAccessControlsApi.java │ │ │ │ ├── ObjectApi.java │ │ │ │ └── ResumableUploadApi.java │ │ │ ├── handlers/ │ │ │ │ ├── GoogleCloudStorageClientErrorRetryHandler.java │ │ │ │ ├── GoogleCloudStorageErrorHandler.java │ │ │ │ └── GoogleCloudStorageRedirectRetryHandler.java │ │ │ ├── options/ │ │ │ │ ├── ComposeObjectOptions.java │ │ │ │ ├── CopyObjectOptions.java │ │ │ │ ├── DeleteBucketOptions.java │ │ │ │ ├── DeleteObjectOptions.java │ │ │ │ ├── GetBucketOptions.java │ │ │ │ ├── GetObjectOptions.java │ │ │ │ ├── InsertBucketOptions.java │ │ │ │ ├── InsertObjectOptions.java │ │ │ │ ├── ListObjectOptions.java │ │ │ │ ├── ListOptions.java │ │ │ │ ├── RewriteObjectOptions.java │ │ │ │ ├── UpdateBucketOptions.java │ │ │ │ └── UpdateObjectOptions.java │ │ │ ├── parser/ │ │ │ │ ├── ParseToPayloadEnclosing.java │ │ │ │ └── ParseToResumableUpload.java │ │ │ └── reference/ │ │ │ └── GoogleCloudStorageConstants.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── googlecloudstorage/ │ │ │ ├── GoogleCloudStorageProviderMetadataTest.java │ │ │ ├── blobstore/ │ │ │ │ └── integration/ │ │ │ │ ├── GoogleCloudStorageBlobIntegrationLiveTest.java │ │ │ │ ├── GoogleCloudStorageBlobLiveTest.java │ │ │ │ ├── GoogleCloudStorageBlobSignerLiveTest.java │ │ │ │ ├── GoogleCloudStorageContainerIntegrationLiveTest.java │ │ │ │ └── GoogleCloudStorageContainerLiveTest.java │ │ │ ├── features/ │ │ │ │ ├── BucketAccessControlsApiExpectTest.java │ │ │ │ ├── BucketAccessControlsApiLiveTest.java │ │ │ │ ├── BucketApiExpectTest.java │ │ │ │ ├── BucketApiLiveTest.java │ │ │ │ ├── DefaultObjectAccessControlsApiExpectTest.java │ │ │ │ ├── DefaultObjectAccessControlsApiLiveTest.java │ │ │ │ ├── ObjectAccessControlsApiExpectTest.java │ │ │ │ ├── ObjectApiLiveTest.java │ │ │ │ ├── ObjectApiMockTest.java │ │ │ │ └── ResumableUploadApiLiveTest.java │ │ │ ├── handlers/ │ │ │ │ └── GoogleCloudStorageErrorHandlerTest.java │ │ │ ├── internal/ │ │ │ │ ├── BaseGoogleCloudStorageApiExpectTest.java │ │ │ │ ├── BaseGoogleCloudStorageApiLiveTest.java │ │ │ │ ├── BaseGoogleCloudStorageApiMockTest.java │ │ │ │ ├── BaseGoogleCloudStorageExpectTest.java │ │ │ │ └── BaseGoogleCloudStorageParseTest.java │ │ │ └── parse/ │ │ │ ├── BucketAclGetTest.java │ │ │ ├── BucketAclInsertTest.java │ │ │ ├── BucketAclListTest.java │ │ │ ├── BucketAclUpdateTest.java │ │ │ ├── BucketUpdateTest.java │ │ │ ├── DefaultObjectAclGetTest.java │ │ │ ├── DefaultObjectAclInsertTest.java │ │ │ ├── DefaultObjectAclListTest.java │ │ │ ├── FullBucketGetTest.java │ │ │ ├── NoAclBucketListTest.java │ │ │ ├── NoAclBucketTest.java │ │ │ ├── ObjectAclGetTest.java │ │ │ ├── ObjectAclInsertTest.java │ │ │ ├── ObjectAclListTest.java │ │ │ ├── ObjectAclUpdateTest.java │ │ │ ├── ParseGoogleCloudStorageObject.java │ │ │ ├── ParseGoogleCloudStorageObjectListTest.java │ │ │ └── ParseObjectRewriteResponse.java │ │ └── resources/ │ │ ├── bucket_acl_get.json │ │ ├── bucket_acl_insert_initial.json │ │ ├── bucket_acl_insert_response.json │ │ ├── bucket_acl_list.json │ │ ├── bucket_acl_update_initial.json │ │ ├── bucket_acl_update_response.json │ │ ├── bucket_insert_request_payload.json │ │ ├── bucket_update_request_payload.json │ │ ├── bucket_update_response.json │ │ ├── default_object_acl_get.json │ │ ├── default_object_acl_insert_request_payload.json │ │ ├── default_object_acl_insert_response.json │ │ ├── default_object_acl_list.json │ │ ├── default_object_acl_update_initial.json │ │ ├── default_object_acl_update_request_payload.json │ │ ├── full_bucket_get.json │ │ ├── list_bucket_with_options.json │ │ ├── logback.xml │ │ ├── no_acl_bucket.json │ │ ├── no_acl_bucket_list.json │ │ ├── object_acl_get.json │ │ ├── object_acl_insert_request_payload.json │ │ ├── object_acl_insert_response.json │ │ ├── object_acl_list.json │ │ ├── object_acl_request_payload.json │ │ ├── object_acl_update_initial.json │ │ ├── object_acl_update_response.json │ │ ├── object_compose_request.json │ │ ├── object_encoded_get.json │ │ ├── object_get.json │ │ ├── object_list.json │ │ └── object_rewrite.json │ ├── google-compute-engine/ │ │ ├── README.md │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── googlecomputeengine/ │ │ │ ├── GoogleComputeEngineApi.java │ │ │ ├── GoogleComputeEngineApiMetadata.java │ │ │ ├── GoogleComputeEngineFallbacks.java │ │ │ ├── GoogleComputeEngineProviderMetadata.java │ │ │ ├── binders/ │ │ │ │ ├── DiskCreationBinder.java │ │ │ │ ├── FirewallBinder.java │ │ │ │ ├── ForwardingRuleCreationBinder.java │ │ │ │ ├── HttpHealthCheckCreationBinder.java │ │ │ │ ├── RouteBinder.java │ │ │ │ ├── TargetPoolChangeHealthChecksBinder.java │ │ │ │ ├── TargetPoolChangeInstancesBinder.java │ │ │ │ └── TargetPoolMapofListofMapGenericBinder.java │ │ │ ├── compute/ │ │ │ │ ├── GoogleComputeEngineService.java │ │ │ │ ├── GoogleComputeEngineServiceAdapter.java │ │ │ │ ├── config/ │ │ │ │ │ └── GoogleComputeEngineServiceContextModule.java │ │ │ │ ├── domain/ │ │ │ │ │ └── internal/ │ │ │ │ │ ├── GoogleComputeEngineArbitraryCpuRamTemplateBuilderImpl.java │ │ │ │ │ └── RegionAndName.java │ │ │ │ ├── functions/ │ │ │ │ │ ├── FirewallTagNamingConvention.java │ │ │ │ │ ├── GoogleComputeEngineImageToImage.java │ │ │ │ │ ├── ImageNameToOperatingSystem.java │ │ │ │ │ ├── InstanceToNodeMetadata.java │ │ │ │ │ ├── MachineTypeToHardware.java │ │ │ │ │ ├── OrphanedGroupsFromDeadNodes.java │ │ │ │ │ ├── ResetWindowsPassword.java │ │ │ │ │ └── Resources.java │ │ │ │ ├── loaders/ │ │ │ │ │ ├── DiskURIToImage.java │ │ │ │ │ └── SubnetworkLoader.java │ │ │ │ ├── options/ │ │ │ │ │ └── GoogleComputeEngineTemplateOptions.java │ │ │ │ ├── predicates/ │ │ │ │ │ ├── AtomicInstanceVisible.java │ │ │ │ │ ├── AtomicOperationDone.java │ │ │ │ │ └── GroupIsEmpty.java │ │ │ │ └── strategy/ │ │ │ │ └── CreateNodesWithGroupEncodedIntoNameThenAddToSet.java │ │ │ ├── config/ │ │ │ │ ├── GoogleComputeEngineHttpApiModule.java │ │ │ │ ├── GoogleComputeEngineParserModule.java │ │ │ │ └── GoogleComputeEngineProperties.java │ │ │ ├── domain/ │ │ │ │ ├── Address.java │ │ │ │ ├── AttachDisk.java │ │ │ │ ├── BackendService.java │ │ │ │ ├── Deprecated.java │ │ │ │ ├── Disk.java │ │ │ │ ├── DiskType.java │ │ │ │ ├── Firewall.java │ │ │ │ ├── ForwardingRule.java │ │ │ │ ├── HealthStatus.java │ │ │ │ ├── HttpHealthCheck.java │ │ │ │ ├── Image.java │ │ │ │ ├── Instance.java │ │ │ │ ├── KeyValuePair.java │ │ │ │ ├── License.java │ │ │ │ ├── MachineType.java │ │ │ │ ├── Metadata.java │ │ │ │ ├── Network.java │ │ │ │ ├── NewInstance.java │ │ │ │ ├── NewTargetInstance.java │ │ │ │ ├── Operation.java │ │ │ │ ├── Project.java │ │ │ │ ├── Quota.java │ │ │ │ ├── Region.java │ │ │ │ ├── Route.java │ │ │ │ ├── Snapshot.java │ │ │ │ ├── Subnetwork.java │ │ │ │ ├── Tags.java │ │ │ │ ├── TargetHttpProxy.java │ │ │ │ ├── TargetInstance.java │ │ │ │ ├── TargetPool.java │ │ │ │ ├── UrlMap.java │ │ │ │ ├── UrlMapValidateResult.java │ │ │ │ ├── Warning.java │ │ │ │ └── Zone.java │ │ │ ├── features/ │ │ │ │ ├── AddressApi.java │ │ │ │ ├── AggregatedListApi.java │ │ │ │ ├── BackendServiceApi.java │ │ │ │ ├── DiskApi.java │ │ │ │ ├── DiskTypeApi.java │ │ │ │ ├── FirewallApi.java │ │ │ │ ├── ForwardingRuleApi.java │ │ │ │ ├── HttpHealthCheckApi.java │ │ │ │ ├── ImageApi.java │ │ │ │ ├── InstanceApi.java │ │ │ │ ├── LicenseApi.java │ │ │ │ ├── MachineTypeApi.java │ │ │ │ ├── NetworkApi.java │ │ │ │ ├── OperationApi.java │ │ │ │ ├── ProjectApi.java │ │ │ │ ├── RegionApi.java │ │ │ │ ├── RouteApi.java │ │ │ │ ├── SnapshotApi.java │ │ │ │ ├── SubnetworkApi.java │ │ │ │ ├── TargetHttpProxyApi.java │ │ │ │ ├── TargetInstanceApi.java │ │ │ │ ├── TargetPoolApi.java │ │ │ │ ├── UrlMapApi.java │ │ │ │ └── ZoneApi.java │ │ │ ├── handlers/ │ │ │ │ └── GoogleComputeEngineErrorHandler.java │ │ │ ├── internal/ │ │ │ │ ├── BaseArg0ToIteratorOfListPage.java │ │ │ │ ├── BaseCallerArg0ToIteratorOfListPage.java │ │ │ │ └── BaseToIteratorOfListPage.java │ │ │ └── options/ │ │ │ ├── AddressCreationOptions.java │ │ │ ├── BackendServiceOptions.java │ │ │ ├── DeprecateOptions.java │ │ │ ├── DiskCreationOptions.java │ │ │ ├── FirewallOptions.java │ │ │ ├── ForwardingRuleCreationOptions.java │ │ │ ├── HttpHealthCheckCreationOptions.java │ │ │ ├── ImageCreationOptions.java │ │ │ ├── ListOptions.java │ │ │ ├── NetworkCreationOptions.java │ │ │ ├── RouteOptions.java │ │ │ ├── SubnetworkCreationOptions.java │ │ │ ├── TargetHttpProxyOptions.java │ │ │ ├── TargetPoolCreationOptions.java │ │ │ └── UrlMapOptions.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── googlecomputeengine/ │ │ │ ├── GoogleComputeEngineProviderMetadataTest.java │ │ │ ├── binders/ │ │ │ │ ├── DiskCreationBinderTest.java │ │ │ │ ├── ForwardingRuleCreationBinderTest.java │ │ │ │ ├── HttpHealthCheckCreationBinderTest.java │ │ │ │ └── TargetPoolAddInstanceBinderTest.java │ │ │ ├── compute/ │ │ │ │ ├── GoogleComputeEngineServiceLiveTest.java │ │ │ │ ├── GoogleComputeEngineServiceMockTest.java │ │ │ │ ├── GoogleComputeEngineTemplateBuilderLiveTest.java │ │ │ │ ├── domain/ │ │ │ │ │ └── internal/ │ │ │ │ │ └── GoogleComputeEngineArbitraryCpuRamTemplateBuilderImplTest.java │ │ │ │ ├── functions/ │ │ │ │ │ ├── GoogleComputeEngineImageToImageTest.java │ │ │ │ │ ├── ImageNameToOperatingSystemTest.java │ │ │ │ │ ├── InstanceToNodeMetadataTest.java │ │ │ │ │ ├── OrphanedGroupsFromDeadNodesTest.java │ │ │ │ │ ├── ResetWindowsPasswordTest.java │ │ │ │ │ └── ResourcesMockTest.java │ │ │ │ └── loaders/ │ │ │ │ └── DiskURIToImageTest.java │ │ │ ├── config/ │ │ │ │ └── UseApiToResolveProjectNameMockTest.java │ │ │ ├── features/ │ │ │ │ ├── AddressApiLiveTest.java │ │ │ │ ├── AddressApiMockTest.java │ │ │ │ ├── AggregatedListApiLiveTest.java │ │ │ │ ├── AggregatedListApiMockTest.java │ │ │ │ ├── BackendServiceApiLiveTest.java │ │ │ │ ├── BackendServiceApiMockTest.java │ │ │ │ ├── DiskApiLiveTest.java │ │ │ │ ├── DiskApiMockTest.java │ │ │ │ ├── DiskTypeApiLiveTest.java │ │ │ │ ├── DiskTypeApiMockTest.java │ │ │ │ ├── FirewallApiLiveTest.java │ │ │ │ ├── FirewallApiMockTest.java │ │ │ │ ├── ForwardingRuleApiLiveTest.java │ │ │ │ ├── ForwardingRuleApiMockTest.java │ │ │ │ ├── GlobalForwardingRuleApiLiveTest.java │ │ │ │ ├── GlobalForwardingRuleApiMockTest.java │ │ │ │ ├── HttpHealthCheckApiLiveTest.java │ │ │ │ ├── HttpHealthCheckApiMockTest.java │ │ │ │ ├── ImageApiLiveTest.java │ │ │ │ ├── ImageApiMockTest.java │ │ │ │ ├── InstanceApiLiveTest.java │ │ │ │ ├── InstanceApiMockTest.java │ │ │ │ ├── InstanceApiWindowsLiveTest.java │ │ │ │ ├── LicenseApiLiveTest.java │ │ │ │ ├── LicenseApiMockTest.java │ │ │ │ ├── MachineTypeApiLiveTest.java │ │ │ │ ├── MachineTypeApiMockTest.java │ │ │ │ ├── NetworkApiLiveTest.java │ │ │ │ ├── NetworkApiMockTest.java │ │ │ │ ├── OperationApiLiveTest.java │ │ │ │ ├── OperationApiMockTest.java │ │ │ │ ├── ProjectApiLiveTest.java │ │ │ │ ├── ProjectApiMockTest.java │ │ │ │ ├── RegionApiLiveTest.java │ │ │ │ ├── RegionApiMockTest.java │ │ │ │ ├── RouteApiLiveTest.java │ │ │ │ ├── RouteApiMockTest.java │ │ │ │ ├── SnapshotApiLiveTest.java │ │ │ │ ├── SnapshotApiMockTest.java │ │ │ │ ├── SubnetworkApiLiveTest.java │ │ │ │ ├── SubnetworkApiMockTest.java │ │ │ │ ├── TargetHttpProxyApiLiveTest.java │ │ │ │ ├── TargetHttpProxyApiMockTest.java │ │ │ │ ├── TargetInstanceApiLiveTest.java │ │ │ │ ├── TargetInstanceApiMockTest.java │ │ │ │ ├── TargetPoolApiLiveTest.java │ │ │ │ ├── TargetPoolApiMockTest.java │ │ │ │ ├── UrlMapApiLiveTest.java │ │ │ │ ├── UrlMapApiMockTest.java │ │ │ │ ├── ZoneApiLiveTest.java │ │ │ │ └── ZoneApiMockTest.java │ │ │ ├── handlers/ │ │ │ │ └── GoogleComputeEngineErrorHandlerTest.java │ │ │ ├── internal/ │ │ │ │ ├── BaseGoogleComputeEngineApiLiveTest.java │ │ │ │ ├── BaseGoogleComputeEngineApiMockTest.java │ │ │ │ ├── BaseGoogleComputeEngineExpectTest.java │ │ │ │ ├── BaseGoogleComputeEngineParseTest.java │ │ │ │ ├── GoogleComputeEngineTestModule.java │ │ │ │ └── ToIteratorOfListPageExpectTest.java │ │ │ └── parse/ │ │ │ ├── ParseAddressListTest.java │ │ │ ├── ParseAddressTest.java │ │ │ ├── ParseBackendServiceListTest.java │ │ │ ├── ParseBackendServiceTest.java │ │ │ ├── ParseDiskListTest.java │ │ │ ├── ParseDiskTest.java │ │ │ ├── ParseDiskTypeListTest.java │ │ │ ├── ParseDiskTypeTest.java │ │ │ ├── ParseFirewallListTest.java │ │ │ ├── ParseFirewallTest.java │ │ │ ├── ParseForwardingRuleListTest.java │ │ │ ├── ParseForwardingRuleTest.java │ │ │ ├── ParseGlobalForwardingRuleListTest.java │ │ │ ├── ParseGlobalForwardingRuleTest.java │ │ │ ├── ParseGlobalOperationListTest.java │ │ │ ├── ParseGlobalOperationTest.java │ │ │ ├── ParseHealthStatusTest.java │ │ │ ├── ParseHttpHealthCheckListTest.java │ │ │ ├── ParseHttpHealthCheckTest.java │ │ │ ├── ParseImageListTest.java │ │ │ ├── ParseImageTest.java │ │ │ ├── ParseInstanceListTest.java │ │ │ ├── ParseInstanceSerialOutputTest.java │ │ │ ├── ParseInstanceTest.java │ │ │ ├── ParseLicenseTest.java │ │ │ ├── ParseMachineTypeListTest.java │ │ │ ├── ParseMachineTypeTest.java │ │ │ ├── ParseMetadataTest.java │ │ │ ├── ParseNetworkListTest.java │ │ │ ├── ParseNetworkTest.java │ │ │ ├── ParseOperationTest.java │ │ │ ├── ParseProjectTest.java │ │ │ ├── ParseQuotaTest.java │ │ │ ├── ParseRegionListTest.java │ │ │ ├── ParseRegionOperationTest.java │ │ │ ├── ParseRegionTest.java │ │ │ ├── ParseRouteListTest.java │ │ │ ├── ParseRouteTest.java │ │ │ ├── ParseSnapshotListTest.java │ │ │ ├── ParseSnapshotTest.java │ │ │ ├── ParseSubnetworkListTest.java │ │ │ ├── ParseSubnetworkTest.java │ │ │ ├── ParseTargetHttpProxyListTest.java │ │ │ ├── ParseTargetHttpProxyTest.java │ │ │ ├── ParseTargetInstanceListTest.java │ │ │ ├── ParseTargetInstanceTest.java │ │ │ ├── ParseTargetPoolListTest.java │ │ │ ├── ParseTargetPoolTest.java │ │ │ ├── ParseUrlMapListTest.java │ │ │ ├── ParseUrlMapTest.java │ │ │ ├── ParseUrlMapValidateTest.java │ │ │ ├── ParseZoneListTest.java │ │ │ ├── ParseZoneOperationTest.java │ │ │ ├── ParseZoneTest.java │ │ │ └── SimpleParsingTests.java │ │ └── resources/ │ │ ├── address_get.json │ │ ├── address_insert.json │ │ ├── address_list.json │ │ ├── aggregated_address_list.json │ │ ├── aggregated_address_list_empty.json │ │ ├── aggregated_disk_list.json │ │ ├── aggregated_disk_list_empty.json │ │ ├── aggregated_disktype_list.json │ │ ├── aggregated_disktype_list_empty.json │ │ ├── aggregated_forwarding_rule_list.json │ │ ├── aggregated_forwarding_rule_list_empty.json │ │ ├── aggregated_global_operation_list.json │ │ ├── aggregated_global_operation_list_empty.json │ │ ├── aggregated_instance_list.json │ │ ├── aggregated_instance_list_empty.json │ │ ├── aggregated_machinetype_list.json │ │ ├── aggregated_target_instance_list.json │ │ ├── aggregated_target_instance_list_empty.json │ │ ├── aggregated_target_pool_list.json │ │ ├── aggregated_target_pool_list_empty.json │ │ ├── backend_service_get.json │ │ ├── backend_service_get_health_request.json │ │ ├── backend_service_insert.json │ │ ├── backend_service_list.json │ │ ├── disk_create_snapshot.json │ │ ├── disk_get.json │ │ ├── disk_get_with_source_image.json │ │ ├── disk_get_with_source_snapshot.json │ │ ├── disk_insert.json │ │ ├── disk_insert_ssd.json │ │ ├── disk_list.json │ │ ├── disktype.json │ │ ├── disktype_list.json │ │ ├── disktype_list_central1b.json │ │ ├── disktype_ssd.json │ │ ├── firewall_get.json │ │ ├── firewall_insert.json │ │ ├── firewall_insert_2.json │ │ ├── firewall_insert_3.json │ │ ├── firewall_list.json │ │ ├── firewall_list_compute.json │ │ ├── forwardingrule_get.json │ │ ├── forwardingrule_insert.json │ │ ├── forwardingrule_list.json │ │ ├── forwardingrule_set_target.json │ │ ├── global_forwarding_rule_get.json │ │ ├── global_forwarding_rule_insert.json │ │ ├── global_forwarding_rule_list.json │ │ ├── global_forwarding_rule_setTarget.json │ │ ├── global_operation.json │ │ ├── global_operation_list.json │ │ ├── health_status_get_health.json │ │ ├── httphealthcheck_get.json │ │ ├── httphealthcheck_insert.json │ │ ├── httphealthcheck_list.json │ │ ├── httphealthcheck_patch.json │ │ ├── image_deprecate.json │ │ ├── image_get.json │ │ ├── image_get_for_source_image.json │ │ ├── image_insert.json │ │ ├── image_insert_from_pd.json │ │ ├── image_list.json │ │ ├── image_list_centos.json │ │ ├── image_list_debian.json │ │ ├── image_list_empty.json │ │ ├── image_list_multiple_page_1.json │ │ ├── image_list_multiple_page_2.json │ │ ├── image_list_single_page.json │ │ ├── instance_add_access_config.json │ │ ├── instance_attach_disk.json │ │ ├── instance_get.json │ │ ├── instance_insert.json │ │ ├── instance_insert_2.json │ │ ├── instance_insert_full.json │ │ ├── instance_insert_no_ip.json │ │ ├── instance_insert_simple.json │ │ ├── instance_insert_ssd.json │ │ ├── instance_insert_subnet.json │ │ ├── instance_list.json │ │ ├── instance_list_central1b_empty.json │ │ ├── instance_serial_port.json │ │ ├── instance_serial_port_4_windows.json │ │ ├── instance_set_metadata.json │ │ ├── instance_set_tags.json │ │ ├── license_get.json │ │ ├── list_empty.json │ │ ├── logback-test.xml │ │ ├── machinetype.json │ │ ├── machinetype_list.json │ │ ├── metadata.json │ │ ├── network_get.json │ │ ├── network_get_default.json │ │ ├── network_insert.json │ │ ├── network_insert_custom.json │ │ ├── network_list.json │ │ ├── operation.json │ │ ├── operation_error.json │ │ ├── operation_list.json │ │ ├── project.json │ │ ├── quota.json │ │ ├── region_get.json │ │ ├── region_list.json │ │ ├── region_operation.json │ │ ├── region_operation_list.json │ │ ├── route_get.json │ │ ├── route_insert.json │ │ ├── route_list.json │ │ ├── snapshot_get.json │ │ ├── snapshot_list.json │ │ ├── subnetwork_get.json │ │ ├── subnetwork_insert.json │ │ ├── subnetwork_list.json │ │ ├── tag_insert.json │ │ ├── target_http_proxy_get.json │ │ ├── target_http_proxy_insert.json │ │ ├── target_http_proxy_list.json │ │ ├── target_http_proxy_set_url_map.json │ │ ├── target_instance_get.json │ │ ├── target_instance_insert.json │ │ ├── target_instance_list.json │ │ ├── targetpool_addinstance.json │ │ ├── targetpool_changehealthcheck.json │ │ ├── targetpool_get.json │ │ ├── targetpool_insert.json │ │ ├── targetpool_list.json │ │ ├── targetpool_setbackup.json │ │ ├── test │ │ ├── url_map_get.json │ │ ├── url_map_insert.json │ │ ├── url_map_list.json │ │ ├── url_map_validate.json │ │ ├── url_map_validate_request.json │ │ ├── zone_get.json │ │ ├── zone_list.json │ │ ├── zone_list_short.json │ │ ├── zone_operation.json │ │ ├── zone_operation_error.json │ │ └── zone_operation_list.json │ ├── openhosting-east1/ │ │ ├── README.txt │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── openhosting/ │ │ │ ├── OpenHostingEast1ProviderMetadata.java │ │ │ └── config/ │ │ │ └── OpenHostingEast1ComputeServiceContextModule.java │ │ └── test/ │ │ └── java/ │ │ └── org/ │ │ └── jclouds/ │ │ └── openhosting/ │ │ ├── OpenHostingEast1ApiLiveTest.java │ │ ├── OpenHostingEast1ProviderTest.java │ │ └── compute/ │ │ ├── OpenHostingEast1ComputeServiceLiveTest.java │ │ └── OpenHostingEast1TemplateBuilderLiveTest.java │ ├── packet/ │ │ ├── README.md │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── packet/ │ │ │ ├── PacketApi.java │ │ │ ├── PacketApiMetadata.java │ │ │ ├── PacketProviderMetadata.java │ │ │ ├── compute/ │ │ │ │ ├── PacketComputeServiceAdapter.java │ │ │ │ ├── config/ │ │ │ │ │ └── PacketComputeServiceContextModule.java │ │ │ │ ├── functions/ │ │ │ │ │ ├── DeviceStateToStatus.java │ │ │ │ │ ├── DeviceToNodeMetadata.java │ │ │ │ │ ├── FacilityToLocation.java │ │ │ │ │ ├── OperatingSystemToImage.java │ │ │ │ │ └── PlanToHardware.java │ │ │ │ ├── options/ │ │ │ │ │ └── PacketTemplateOptions.java │ │ │ │ └── strategy/ │ │ │ │ └── CreateSshKeysThenCreateNodes.java │ │ │ ├── config/ │ │ │ │ ├── PacketComputeParserModule.java │ │ │ │ └── PacketHttpApiModule.java │ │ │ ├── domain/ │ │ │ │ ├── BillingCycle.java │ │ │ │ ├── Device.java │ │ │ │ ├── Facility.java │ │ │ │ ├── Href.java │ │ │ │ ├── IpAddress.java │ │ │ │ ├── OperatingSystem.java │ │ │ │ ├── Plan.java │ │ │ │ ├── Pricing.java │ │ │ │ ├── Project.java │ │ │ │ ├── ProvisioningEvent.java │ │ │ │ ├── Specs.java │ │ │ │ ├── SshKey.java │ │ │ │ ├── internal/ │ │ │ │ │ └── PaginatedCollection.java │ │ │ │ └── options/ │ │ │ │ └── ListOptions.java │ │ │ ├── features/ │ │ │ │ ├── DeviceApi.java │ │ │ │ ├── FacilityApi.java │ │ │ │ ├── OperatingSystemApi.java │ │ │ │ ├── PlanApi.java │ │ │ │ ├── ProjectApi.java │ │ │ │ └── SshKeyApi.java │ │ │ ├── filters/ │ │ │ │ ├── AddApiVersionToRequest.java │ │ │ │ └── AddXAuthTokenToRequest.java │ │ │ ├── functions/ │ │ │ │ ├── BaseToPagedIterable.java │ │ │ │ └── HrefToListOptions.java │ │ │ └── handlers/ │ │ │ └── PacketErrorHandler.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── packet/ │ │ │ ├── PacketProviderMetadataTest.java │ │ │ ├── compute/ │ │ │ │ ├── PacketComputeProviderMetadataTest.java │ │ │ │ ├── PacketComputeServiceLiveTest.java │ │ │ │ ├── PacketTemplateBuilderLiveTest.java │ │ │ │ └── internal/ │ │ │ │ ├── BasePacketApiLiveTest.java │ │ │ │ └── BasePacketApiMockTest.java │ │ │ ├── features/ │ │ │ │ ├── DeviceApiLiveTest.java │ │ │ │ ├── DeviceApiMockTest.java │ │ │ │ ├── FacilityApiLiveTest.java │ │ │ │ ├── FacilityApiMockTest.java │ │ │ │ ├── OperatingSystemApiLiveTest.java │ │ │ │ ├── OperatingSystemApiMockTest.java │ │ │ │ ├── PlanApiLiveTest.java │ │ │ │ ├── PlanApiMockTest.java │ │ │ │ ├── ProjectApiLiveTest.java │ │ │ │ ├── ProjectApiMockTest.java │ │ │ │ ├── SshKeyApiLiveTest.java │ │ │ │ └── SshKeyApiMockTest.java │ │ │ └── functions/ │ │ │ └── HrefToListOptionsTest.java │ │ └── resources/ │ │ ├── device-create-req.json │ │ ├── device-create-res.json │ │ ├── device.json │ │ ├── devices-first.json │ │ ├── devices-last.json │ │ ├── devices.json │ │ ├── facilities-first.json │ │ ├── facilities-last.json │ │ ├── facilities.json │ │ ├── logback-test.xml │ │ ├── operatingSystems-first.json │ │ ├── operatingSystems-last.json │ │ ├── operatingSystems.json │ │ ├── plans-first.json │ │ ├── plans-last.json │ │ ├── plans.json │ │ ├── power-off.json │ │ ├── power-on.json │ │ ├── projects-first.json │ │ ├── projects-last.json │ │ ├── projects.json │ │ ├── reboot.json │ │ ├── ssh-key-create-req.json │ │ ├── ssh-key-create-res.json │ │ ├── ssh-key.json │ │ ├── sshKeys-first.json │ │ ├── sshKeys-last.json │ │ ├── sshKeys.json │ │ └── user.json │ ├── pom.xml │ ├── profitbricks/ │ │ ├── README.md │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── profitbricks/ │ │ │ ├── ProfitBricksApi.java │ │ │ ├── ProfitBricksApiMetadata.java │ │ │ ├── ProfitBricksProviderMetadata.java │ │ │ ├── binder/ │ │ │ │ ├── BaseProfitBricksRequestBinder.java │ │ │ │ ├── datacenter/ │ │ │ │ │ ├── CreateDataCenterRequestBinder.java │ │ │ │ │ └── UpdateDataCenterRequestBinder.java │ │ │ │ ├── drive/ │ │ │ │ │ └── AddRomDriveToServerRequestBinder.java │ │ │ │ ├── firewall/ │ │ │ │ │ ├── AddFirewallRuleToNicRequestBinder.java │ │ │ │ │ └── FirewallBinder.java │ │ │ │ ├── loadbalancer/ │ │ │ │ │ ├── CreateLoadBalancerRequestBinder.java │ │ │ │ │ ├── DeregisterLoadBalancerRequestBinder.java │ │ │ │ │ ├── RegisterLoadBalancerRequestBinder.java │ │ │ │ │ └── UpdateLoadBalancerRequestBinder.java │ │ │ │ ├── nic/ │ │ │ │ │ ├── CreateNicRequestBinder.java │ │ │ │ │ ├── SetInternetAccessBinder.java │ │ │ │ │ └── UpdateNicRequestBinder.java │ │ │ │ ├── server/ │ │ │ │ │ ├── CreateServerRequestBinder.java │ │ │ │ │ └── UpdateServerRequestBinder.java │ │ │ │ ├── snapshot/ │ │ │ │ │ ├── CreateSnapshotRequestBinder.java │ │ │ │ │ ├── RollbackSnapshotRequestBinder.java │ │ │ │ │ └── UpdateSnapshotRequestBinder.java │ │ │ │ └── storage/ │ │ │ │ ├── ConnectStorageToServerRequestBinder.java │ │ │ │ ├── CreateStorageRequestBinder.java │ │ │ │ └── UpdateStorageRequestBinder.java │ │ │ ├── compute/ │ │ │ │ ├── ProfitBricksComputeServiceAdapter.java │ │ │ │ ├── concurrent/ │ │ │ │ │ ├── ProvisioningJob.java │ │ │ │ │ └── ProvisioningManager.java │ │ │ │ ├── config/ │ │ │ │ │ └── ProfitBricksComputeServiceContextModule.java │ │ │ │ ├── function/ │ │ │ │ │ ├── ProvisionableToImage.java │ │ │ │ │ ├── ServerToNodeMetadata.java │ │ │ │ │ └── StorageToVolume.java │ │ │ │ └── strategy/ │ │ │ │ ├── AssignDataCenterToTemplate.java │ │ │ │ └── TemplateWithDataCenter.java │ │ │ ├── config/ │ │ │ │ ├── ProfitBricksComputeProperties.java │ │ │ │ └── ProfitBricksHttpApiModule.java │ │ │ ├── domain/ │ │ │ │ ├── AvailabilityZone.java │ │ │ │ ├── DataCenter.java │ │ │ │ ├── Drive.java │ │ │ │ ├── Firewall.java │ │ │ │ ├── Image.java │ │ │ │ ├── IpBlock.java │ │ │ │ ├── LoadBalancer.java │ │ │ │ ├── Location.java │ │ │ │ ├── Nic.java │ │ │ │ ├── OsType.java │ │ │ │ ├── Provisionable.java │ │ │ │ ├── ProvisioningState.java │ │ │ │ ├── Server.java │ │ │ │ ├── ServiceFault.java │ │ │ │ ├── Snapshot.java │ │ │ │ └── Storage.java │ │ │ ├── features/ │ │ │ │ ├── DataCenterApi.java │ │ │ │ ├── DrivesApi.java │ │ │ │ ├── FirewallApi.java │ │ │ │ ├── ImageApi.java │ │ │ │ ├── IpBlockApi.java │ │ │ │ ├── LoadBalancerApi.java │ │ │ │ ├── NicApi.java │ │ │ │ ├── ServerApi.java │ │ │ │ ├── SnapshotApi.java │ │ │ │ └── StorageApi.java │ │ │ ├── handlers/ │ │ │ │ └── ProfitBricksHttpErrorHandler.java │ │ │ ├── http/ │ │ │ │ ├── ResponseStatusFromPayloadHttpCommandExecutorService.java │ │ │ │ ├── filters/ │ │ │ │ │ └── ProfitBricksSoapMessageEnvelope.java │ │ │ │ └── parser/ │ │ │ │ ├── BaseProfitBricksResponseHandler.java │ │ │ │ ├── RequestIdOnlyResponseHandler.java │ │ │ │ ├── ServiceFaultResponseHandler.java │ │ │ │ ├── datacenter/ │ │ │ │ │ ├── BaseDataCenterResponseHandler.java │ │ │ │ │ ├── DataCenterInfoResponseHandler.java │ │ │ │ │ └── DataCenterListResponseHandler.java │ │ │ │ ├── firewall/ │ │ │ │ │ ├── BaseFirewallResponseHandler.java │ │ │ │ │ ├── FirewallListResponseHandler.java │ │ │ │ │ ├── FirewallResponseHandler.java │ │ │ │ │ └── rule/ │ │ │ │ │ ├── BaseFirewallRuleResponseHandler.java │ │ │ │ │ └── FirewallRuleListResponseHandler.java │ │ │ │ ├── image/ │ │ │ │ │ ├── BaseImageResponseHandler.java │ │ │ │ │ ├── ImageInfoResponseHandler.java │ │ │ │ │ └── ImageListResponseHandler.java │ │ │ │ ├── ipblock/ │ │ │ │ │ ├── BaseIpBlockResponseHandler.java │ │ │ │ │ ├── IpBlockListResponseHandler.java │ │ │ │ │ └── IpBlockResponseHandler.java │ │ │ │ ├── loadbalancer/ │ │ │ │ │ ├── BaseLoadBalancerResponseHandler.java │ │ │ │ │ ├── LoadBalancerIdOnlyResponseHandler.java │ │ │ │ │ ├── LoadBalancerListResponseHandler.java │ │ │ │ │ └── LoadBalancerResponseHandler.java │ │ │ │ ├── nic/ │ │ │ │ │ ├── BaseNicResponseHandler.java │ │ │ │ │ ├── NicIdOnlyResponseHandler.java │ │ │ │ │ ├── NicListResponseHandler.java │ │ │ │ │ └── NicResponseHandler.java │ │ │ │ ├── publicip/ │ │ │ │ │ ├── BasePublicIpResponseHandler.java │ │ │ │ │ └── PublicIpListResponseHandler.java │ │ │ │ ├── server/ │ │ │ │ │ ├── BaseServerResponseHandler.java │ │ │ │ │ ├── ServerIdOnlyResponseHandler.java │ │ │ │ │ ├── ServerInfoResponseHandler.java │ │ │ │ │ └── ServerListResponseHandler.java │ │ │ │ ├── snapshot/ │ │ │ │ │ ├── BaseSnapshotResponseHandler.java │ │ │ │ │ ├── SnapshotListResponseHandler.java │ │ │ │ │ └── SnapshotResponseHandler.java │ │ │ │ ├── state/ │ │ │ │ │ └── GetProvisioningStateResponseHandler.java │ │ │ │ └── storage/ │ │ │ │ ├── BaseStorageResponseHandler.java │ │ │ │ ├── StorageIdOnlyResponseHandler.java │ │ │ │ ├── StorageInfoResponseHandler.java │ │ │ │ └── StorageListResponseHandler.java │ │ │ └── util/ │ │ │ ├── MacAddresses.java │ │ │ └── Preconditions.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── profitbricks/ │ │ │ ├── BaseProfitBricksLiveTest.java │ │ │ ├── ProfitBricksProviderMetadataTest.java │ │ │ ├── binder/ │ │ │ │ ├── datacenter/ │ │ │ │ │ ├── CreateDataCenterRequestBinderTest.java │ │ │ │ │ └── UpdateDataCenterRequestBinderTest.java │ │ │ │ ├── drive/ │ │ │ │ │ └── AddRomDriveToServerRequestBinderTest.java │ │ │ │ ├── firewall/ │ │ │ │ │ ├── AddFirewallRuleToNicRequestBinderTest.java │ │ │ │ │ └── FirewallBinderTest.java │ │ │ │ ├── loadbalancer/ │ │ │ │ │ ├── CreateLoadBalancerRequestBinderTest.java │ │ │ │ │ ├── DeregisterLoadBalancerRequestBinderTest.java │ │ │ │ │ ├── RegisterLoadBalancerRequestBinderTest.java │ │ │ │ │ └── UpdateLoadBalancerRequestBinderTest.java │ │ │ │ ├── nic/ │ │ │ │ │ ├── CreateNicRequestBinderTest.java │ │ │ │ │ ├── SetInternetAccessBinderTest.java │ │ │ │ │ └── UpdateNicRequestBinderTest.java │ │ │ │ ├── server/ │ │ │ │ │ ├── CreateServerRequestBinderTest.java │ │ │ │ │ └── UpdateServerRequestBinderTest.java │ │ │ │ ├── snapshot/ │ │ │ │ │ ├── CreateSnapshotRequestBinderTest.java │ │ │ │ │ ├── RollbackSnapshotRequestBinderTest.java │ │ │ │ │ └── UpdateSnapshotRequestBinderTest.java │ │ │ │ └── storage/ │ │ │ │ ├── ConnectStorageToServerRequestBinderTest.java │ │ │ │ ├── CreateStorageRequestBinderTest.java │ │ │ │ └── UpdateStorageRequestBinderTest.java │ │ │ ├── compute/ │ │ │ │ ├── ProfitBricksComputeServiceLiveTest.java │ │ │ │ ├── ProfitBricksTemplateBuilderLiveTest.java │ │ │ │ ├── concurrent/ │ │ │ │ │ └── ProvisioningManagerTest.java │ │ │ │ ├── config/ │ │ │ │ │ └── StatusPredicateTest.java │ │ │ │ └── function/ │ │ │ │ ├── ProvisionableToImageTest.java │ │ │ │ ├── ServerToNodeMetadataTest.java │ │ │ │ └── StorageToVolumeTest.java │ │ │ ├── domain/ │ │ │ │ ├── FirewallRuleBuilderTest.java │ │ │ │ └── ServerBuilderTest.java │ │ │ ├── features/ │ │ │ │ ├── DataCenterApiLiveTest.java │ │ │ │ ├── DataCenterApiMockTest.java │ │ │ │ ├── DrivesApiLiveTest.java │ │ │ │ ├── DrivesApiMockTest.java │ │ │ │ ├── FirewallApiLiveTest.java │ │ │ │ ├── FirewallApiMockTest.java │ │ │ │ ├── ImageApiLiveTest.java │ │ │ │ ├── ImageApiMockTest.java │ │ │ │ ├── IpBlockApiLiveTest.java │ │ │ │ ├── IpBlockApiMockTest.java │ │ │ │ ├── LoadBalancerApiLiveTest.java │ │ │ │ ├── LoadBalancerApiMockTest.java │ │ │ │ ├── NicApiLiveTest.java │ │ │ │ ├── NicApiMockTest.java │ │ │ │ ├── ServerApiLiveTest.java │ │ │ │ ├── ServerApiMockTest.java │ │ │ │ ├── SnapshotApiLiveTest.java │ │ │ │ ├── SnapshotApiMockTest.java │ │ │ │ ├── StorageApiLiveTest.java │ │ │ │ └── StorageApiMockTest.java │ │ │ ├── http/ │ │ │ │ ├── ResponseStatusFromPayloadHttpCommandExecutorServiceTest.java │ │ │ │ ├── filters/ │ │ │ │ │ └── ProfitBricksSoapMessageEnvelopeTest.java │ │ │ │ └── parser/ │ │ │ │ ├── BaseResponseHandlerTest.java │ │ │ │ ├── RequestIdOnlyResponseHandlerTest.java │ │ │ │ ├── ServiceFaultResponseHandlerTest.java │ │ │ │ ├── datacenter/ │ │ │ │ │ ├── DataCenterInfoResponseHandlerTest.java │ │ │ │ │ └── DataCenterListResponseHandlerTest.java │ │ │ │ ├── firewall/ │ │ │ │ │ ├── FirewallListResponseHandlerTest.java │ │ │ │ │ └── FirewallResponseHandlerTest.java │ │ │ │ ├── image/ │ │ │ │ │ ├── ImageInfoResponseHandlerTest.java │ │ │ │ │ └── ImageListResponseHandlerTest.java │ │ │ │ ├── ipblock/ │ │ │ │ │ ├── IpBlockListResponseHandlerTest.java │ │ │ │ │ └── IpBlockResponseHandlerTest.java │ │ │ │ ├── loadbalancer/ │ │ │ │ │ ├── LoadBalancerIdOnlyResponseHandlerTest.java │ │ │ │ │ ├── LoadBalancerListResponseHandlerTest.java │ │ │ │ │ └── LoadBalancerResponseHandlerTest.java │ │ │ │ ├── nic/ │ │ │ │ │ ├── NicIdOnlyResponseHandlerTest.java │ │ │ │ │ ├── NicListResponseHandlerTest.java │ │ │ │ │ └── NicResponseHandlerTest.java │ │ │ │ ├── server/ │ │ │ │ │ ├── ServerIdOnlyResponseHandlerTest.java │ │ │ │ │ ├── ServerInfoResponseHandlerTest.java │ │ │ │ │ └── ServerListResponseHandlerTest.java │ │ │ │ ├── snapshot/ │ │ │ │ │ ├── SnapshotListResponseHandlerTest.java │ │ │ │ │ └── SnapshotResponseHandlerTest.java │ │ │ │ ├── state/ │ │ │ │ │ └── GetProvisioningStateResponseHandlerTest.java │ │ │ │ └── storage/ │ │ │ │ ├── StorageIdOnlyResponseHandlerTest.java │ │ │ │ ├── StorageInfoResponseHandlerTest.java │ │ │ │ └── StorageListResponseHandlerTest.java │ │ │ ├── internal/ │ │ │ │ └── BaseProfitBricksMockTest.java │ │ │ └── util/ │ │ │ └── MacAddressesTest.java │ │ └── resources/ │ │ ├── datacenter/ │ │ │ ├── datacenter-cleared.xml │ │ │ ├── datacenter-created.xml │ │ │ ├── datacenter-deleted.xml │ │ │ ├── datacenter-not-found.xml │ │ │ ├── datacenter-state-inprocess.xml │ │ │ ├── datacenter-state.xml │ │ │ ├── datacenter-updated.xml │ │ │ ├── datacenter.xml │ │ │ └── datacenters.xml │ │ ├── drives/ │ │ │ ├── drives-add.xml │ │ │ └── drives-remove.xml │ │ ├── fault-400.xml │ │ ├── fault-404.xml │ │ ├── fault-413.xml │ │ ├── fault-500.xml │ │ ├── firewall/ │ │ │ ├── firewall-activate.xml │ │ │ ├── firewall-addtonic.xml │ │ │ ├── firewall-deactivate.xml │ │ │ ├── firewall-delete.xml │ │ │ ├── firewall-remove.xml │ │ │ ├── firewall.xml │ │ │ └── firewalls.xml │ │ ├── html/ │ │ │ ├── fault-401.html │ │ │ └── maintenance-503.html │ │ ├── image/ │ │ │ ├── image-not-found.xml │ │ │ ├── image.xml │ │ │ └── images.xml │ │ ├── ipblock/ │ │ │ ├── ipblock-addtonic.xml │ │ │ ├── ipblock-release.xml │ │ │ ├── ipblock-removefromnic.xml │ │ │ ├── ipblock-reserve.xml │ │ │ ├── ipblock.xml │ │ │ └── ipblocks.xml │ │ ├── loadbalancer/ │ │ │ ├── loadbalancer-create.xml │ │ │ ├── loadbalancer-delete.xml │ │ │ ├── loadbalancer-deregister.xml │ │ │ ├── loadbalancer-register.xml │ │ │ ├── loadbalancer-update.xml │ │ │ ├── loadbalancer.xml │ │ │ └── loadbalancers.xml │ │ ├── logback-test.xml │ │ ├── nic/ │ │ │ ├── nic-create.xml │ │ │ ├── nic-delete.xml │ │ │ ├── nic-internetaccess.xml │ │ │ ├── nic-update.xml │ │ │ ├── nic.xml │ │ │ └── nics.xml │ │ ├── server/ │ │ │ ├── server-create.xml │ │ │ ├── server-delete.xml │ │ │ ├── server-reset.xml │ │ │ ├── server-start.xml │ │ │ ├── server-state-inprocess.xml │ │ │ ├── server-stop.xml │ │ │ ├── server-update.xml │ │ │ ├── server.xml │ │ │ └── servers.xml │ │ ├── snapshot/ │ │ │ ├── snapshot-create.xml │ │ │ ├── snapshot-delete.xml │ │ │ ├── snapshot-rollback.xml │ │ │ ├── snapshot-state-inprocess.xml │ │ │ ├── snapshot-update.xml │ │ │ ├── snapshot.xml │ │ │ └── snapshots.xml │ │ └── storage/ │ │ ├── storage-connect.xml │ │ ├── storage-create.xml │ │ ├── storage-delete.xml │ │ ├── storage-disconnect.xml │ │ ├── storage-state-inprocess.xml │ │ ├── storage-update.xml │ │ ├── storage.xml │ │ └── storages.xml │ ├── rackspace-cloudblockstorage-uk/ │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── rackspace/ │ │ │ └── cloudblockstorage/ │ │ │ └── uk/ │ │ │ └── CloudBlockStorageUKProviderMetadata.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── rackspace/ │ │ │ └── cloudblockstorage/ │ │ │ └── uk/ │ │ │ ├── CloudBlockStorageUKProviderMetadataExpectTest.java │ │ │ ├── CloudBlockStorageUKProviderTest.java │ │ │ └── features/ │ │ │ ├── CloudBlockStorageUKVolumeAndSnapshotApiLiveTest.java │ │ │ └── CloudBlockStorageUKVolumeTypeApiLiveTest.java │ │ └── resources/ │ │ └── access_rax_uk.json │ ├── rackspace-cloudblockstorage-us/ │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── rackspace/ │ │ │ └── cloudblockstorage/ │ │ │ └── us/ │ │ │ └── CloudBlockStorageUSProviderMetadata.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── rackspace/ │ │ │ └── cloudblockstorage/ │ │ │ └── us/ │ │ │ ├── CloudBlockStorageUSProviderMetadataExpectTest.java │ │ │ ├── CloudBlockStorageUSProviderTest.java │ │ │ └── features/ │ │ │ ├── CloudBlockStorageUSVolumeAndSnapshotApiLiveTest.java │ │ │ └── CloudBlockStorageUSVolumeTypeApiLiveTest.java │ │ └── resources/ │ │ └── access_rax_us.json │ ├── rackspace-clouddatabases-uk/ │ │ ├── README.md │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── rackspace/ │ │ │ └── clouddatabases/ │ │ │ └── uk/ │ │ │ └── CloudDatabasesUKProviderMetadata.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── rackspace/ │ │ │ └── clouddatabases/ │ │ │ └── uk/ │ │ │ ├── CloudDatabasesUKProviderMetadataExpectTest.java │ │ │ ├── CloudDatabasesUKProviderTest.java │ │ │ └── features/ │ │ │ ├── CloudDatabasesUKDatabaseApiLiveTest.java │ │ │ ├── CloudDatabasesUKFlavorApiLiveTest.java │ │ │ ├── CloudDatabasesUKInstanceApiLiveTest.java │ │ │ └── CloudDatabasesUKUserApiLiveTest.java │ │ └── resources/ │ │ ├── access_rax_uk.json │ │ └── logback.xml │ ├── rackspace-clouddatabases-us/ │ │ ├── README.md │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── rackspace/ │ │ │ └── clouddatabases/ │ │ │ └── us/ │ │ │ └── CloudDatabasesUSProviderMetadata.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── rackspace/ │ │ │ └── clouddatabases/ │ │ │ └── us/ │ │ │ ├── CloudDatabasesUSProviderMetadataExpectTest.java │ │ │ ├── CloudDatabasesUSProviderTest.java │ │ │ └── features/ │ │ │ ├── CloudDatabasesUSDatabaseApiLiveTest.java │ │ │ ├── CloudDatabasesUSFlavorApiLiveTest.java │ │ │ ├── CloudDatabasesUSInstanceApiLiveTest.java │ │ │ └── CloudDatabasesUSUserApiLiveTest.java │ │ └── resources/ │ │ └── logback.xml │ ├── rackspace-clouddns-uk/ │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── rackspace/ │ │ │ └── clouddns/ │ │ │ └── uk/ │ │ │ └── CloudDNSUKProviderMetadata.java │ │ └── test/ │ │ └── java/ │ │ └── org/ │ │ └── jclouds/ │ │ └── rackspace/ │ │ └── clouddns/ │ │ └── uk/ │ │ └── features/ │ │ ├── CloudDNSUKDomainApiLiveTest.java │ │ ├── CloudDNSUKLimitApiLiveTest.java │ │ ├── CloudDNSUKProviderTest.java │ │ └── CloudDNSUKRecordApiLiveTest.java │ ├── rackspace-clouddns-us/ │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── rackspace/ │ │ │ └── clouddns/ │ │ │ └── us/ │ │ │ └── CloudDNSUSProviderMetadata.java │ │ └── test/ │ │ └── java/ │ │ └── org/ │ │ └── jclouds/ │ │ └── rackspace/ │ │ └── clouddns/ │ │ └── us/ │ │ └── features/ │ │ ├── CloudDNSUSDomainApiLiveTest.java │ │ ├── CloudDNSUSLimitApiLiveTest.java │ │ ├── CloudDNSUSProviderTest.java │ │ ├── CloudDNSUSRecordApiLiveTest.java │ │ └── CloudDNSUSReverseDNSApiLiveTest.java │ ├── rackspace-cloudfiles-uk/ │ │ ├── README.md │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── rackspace/ │ │ │ └── cloudfiles/ │ │ │ └── uk/ │ │ │ └── CloudFilesUKProviderMetadata.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── rackspace/ │ │ │ └── cloudfiles/ │ │ │ └── uk/ │ │ │ ├── CloudFilesUKProviderTest.java │ │ │ ├── blobstore/ │ │ │ │ └── integration/ │ │ │ │ ├── CloudFilesUKBlobIntegrationLiveTest.java │ │ │ │ ├── CloudFilesUKBlobLiveTest.java │ │ │ │ ├── CloudFilesUKBlobSignerLiveTest.java │ │ │ │ ├── CloudFilesUKContainerIntegrationLiveTest.java │ │ │ │ ├── CloudFilesUKContainerLiveTest.java │ │ │ │ └── CloudFilesUKServiceIntegrationLiveTest.java │ │ │ └── features/ │ │ │ ├── CloudFilesUKDynamicLargeObjectApiLiveTest.java │ │ │ ├── CloudFilesUKObjectApiLiveTest.java │ │ │ └── CloudFilesUKStaticLargeObjectApiLiveTest.java │ │ └── resources/ │ │ └── logback.xml │ ├── rackspace-cloudfiles-us/ │ │ ├── README.md │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── rackspace/ │ │ │ └── cloudfiles/ │ │ │ └── us/ │ │ │ └── CloudFilesUSProviderMetadata.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── rackspace/ │ │ │ └── cloudfiles/ │ │ │ └── us/ │ │ │ ├── CloudFilesUSProviderTest.java │ │ │ ├── blobstore/ │ │ │ │ └── integration/ │ │ │ │ ├── CloudFilesUSBlobIntegrationLiveTest.java │ │ │ │ ├── CloudFilesUSBlobIntegrationParallelLiveTest.java │ │ │ │ ├── CloudFilesUSBlobLiveTest.java │ │ │ │ ├── CloudFilesUSBlobSignerLiveTest.java │ │ │ │ ├── CloudFilesUSContainerIntegrationLiveTest.java │ │ │ │ ├── CloudFilesUSContainerLiveTest.java │ │ │ │ └── CloudFilesUSServiceIntegrationLiveTest.java │ │ │ └── features/ │ │ │ ├── CloudFilesUSAccountApiLiveTest.java │ │ │ ├── CloudFilesUSDynamicLargeObjectApiLiveTest.java │ │ │ ├── CloudFilesUSObjectApiLiveTest.java │ │ │ └── CloudFilesUSStaticLargeObjectApiLiveTest.java │ │ └── resources/ │ │ └── logback.xml │ ├── rackspace-cloudloadbalancers-uk/ │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── rackspace/ │ │ │ └── cloudloadbalancers/ │ │ │ └── uk/ │ │ │ └── CloudLoadBalancersUKProviderMetadata.java │ │ └── test/ │ │ └── java/ │ │ └── org/ │ │ └── jclouds/ │ │ └── rackspace/ │ │ └── cloudloadbalancers/ │ │ └── uk/ │ │ ├── CloudLoadBalancersUKLoadBalancerClientLiveTest.java │ │ ├── CloudLoadBalancersUKNodeClientLiveTest.java │ │ └── CloudLoadBalancersUKProviderTest.java │ ├── rackspace-cloudloadbalancers-us/ │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── rackspace/ │ │ │ └── cloudloadbalancers/ │ │ │ └── us/ │ │ │ └── CloudLoadBalancersUSProviderMetadata.java │ │ └── test/ │ │ └── java/ │ │ └── org/ │ │ └── jclouds/ │ │ └── rackspace/ │ │ └── cloudloadbalancers/ │ │ └── us/ │ │ ├── CloudLoadBalancersUSLoadBalancerClientLiveTest.java │ │ ├── CloudLoadBalancersUSNodeClientLiveTest.java │ │ └── CloudLoadBalancersUSProviderTest.java │ ├── rackspace-cloudnetworks-uk/ │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── rackspace/ │ │ │ └── cloudnetworks/ │ │ │ └── uk/ │ │ │ └── CloudNetworksUKProviderMetadata.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── rackspace/ │ │ │ └── cloudnetworks/ │ │ │ └── uk/ │ │ │ ├── CloudNetworksUKNetworkApiLiveTest.java │ │ │ ├── CloudNetworksUKPortApiLiveTest.java │ │ │ ├── CloudNetworksUKProviderTest.java │ │ │ └── CloudNetworksUKSubnetApiLiveTest.java │ │ └── resources/ │ │ └── logback.xml │ ├── rackspace-cloudnetworks-us/ │ │ ├── README.md │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── rackspace/ │ │ │ └── cloudnetworks/ │ │ │ └── us/ │ │ │ └── CloudNetworksUSProviderMetadata.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── rackspace/ │ │ │ └── cloudnetworks/ │ │ │ └── us/ │ │ │ ├── CloudNetworksUSNetworkApiLiveTest.java │ │ │ ├── CloudNetworksUSPortApiLiveTest.java │ │ │ ├── CloudNetworksUSProviderTest.java │ │ │ ├── CloudNetworksUSSecurityGroupApiLiveTest.java │ │ │ └── CloudNetworksUSSubnetApiLiveTest.java │ │ └── resources/ │ │ └── logback.xml │ ├── rackspace-cloudservers-uk/ │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── rackspace/ │ │ │ └── cloudservers/ │ │ │ └── uk/ │ │ │ ├── CloudServersUKProviderMetadata.java │ │ │ └── config/ │ │ │ ├── CloudServersUKComputeServiceContextModule.java │ │ │ └── CloudServersUKHttpApiModule.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── rackspace/ │ │ │ └── cloudservers/ │ │ │ └── uk/ │ │ │ ├── CloudServersUKProviderMetadataExpectTest.java │ │ │ ├── CloudServersUKProviderTest.java │ │ │ ├── compute/ │ │ │ │ ├── CloudServersUKComputeServiceLiveTest.java │ │ │ │ ├── CloudServersUKTemplateBuilderLiveTest.java │ │ │ │ └── extensions/ │ │ │ │ ├── CloudServersUKImageExtensionLivetest.java │ │ │ │ └── CloudServersUKVolumeAttachmentExtensionLiveTest.java │ │ │ └── features/ │ │ │ ├── CloudServersUKFlavorApiLiveTest.java │ │ │ ├── CloudServersUKImageApiLiveTest.java │ │ │ └── CloudServersUKServerApiLiveTest.java │ │ └── resources/ │ │ ├── access_rax_uk.json │ │ └── raxImages.json │ ├── rackspace-cloudservers-us/ │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── rackspace/ │ │ │ └── cloudservers/ │ │ │ └── us/ │ │ │ ├── CloudServersUSProviderMetadata.java │ │ │ └── config/ │ │ │ ├── CloudServersUSComputeServiceContextModule.java │ │ │ └── CloudServersUSHttpApiModule.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── rackspace/ │ │ │ └── cloudservers/ │ │ │ └── us/ │ │ │ ├── CloudServersUSProviderMetadataExpectTest.java │ │ │ ├── CloudServersUSProviderTest.java │ │ │ ├── compute/ │ │ │ │ ├── CloudServersUSComputeServiceLiveTest.java │ │ │ │ ├── CloudServersUSTemplateBuilderLiveTest.java │ │ │ │ └── extensions/ │ │ │ │ ├── CloudServersUSImageExtensionLivetest.java │ │ │ │ └── CloudServersUSVolumeAttachmentExtensionLiveTest.java │ │ │ └── features/ │ │ │ ├── CloudServersUSFlavorApiLiveTest.java │ │ │ ├── CloudServersUSImageApiLiveTest.java │ │ │ └── CloudServersUSServerApiLiveTest.java │ │ └── resources/ │ │ ├── access_rax_us.json │ │ └── raxImages.json │ ├── serverlove-z1-man/ │ │ ├── README.txt │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ ├── java/ │ │ │ │ └── org/ │ │ │ │ └── jclouds/ │ │ │ │ └── serverlove/ │ │ │ │ ├── ServerloveManchesterProviderMetadata.java │ │ │ │ ├── config/ │ │ │ │ │ └── ServerloveImagesModule.java │ │ │ │ └── suppliers/ │ │ │ │ └── FixedWellKnownImageSupplier.java │ │ │ └── resources/ │ │ │ └── serverlove-z1-man/ │ │ │ └── preinstalled_images.json │ │ └── test/ │ │ └── java/ │ │ └── org/ │ │ └── jclouds/ │ │ └── serverlove/ │ │ ├── ServerloveManchesterApiLiveTest.java │ │ ├── ServerloveManchesterProviderTest.java │ │ └── compute/ │ │ ├── ServerloveManchesterComputeServiceLiveTest.java │ │ └── ServerloveManchesterTemplateBuilderLiveTest.java │ ├── skalicloud-sdg-my/ │ │ ├── README.txt │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── skalicloud/ │ │ │ └── SkaliCloudMalaysiaProviderMetadata.java │ │ └── test/ │ │ └── java/ │ │ └── org/ │ │ └── jclouds/ │ │ └── skalicloud/ │ │ ├── SkaliCloudMalaysiaApiLiveTest.java │ │ ├── SkaliCloudMalaysiaProviderTest.java │ │ └── compute/ │ │ ├── SkaliCloudMalaysiaComputeServiceLiveTest.java │ │ └── SkaliCloudMalaysiaTemplateBuilderLiveTest.java │ ├── softlayer/ │ │ ├── bnd.bnd │ │ ├── pom.xml │ │ └── src/ │ │ ├── main/ │ │ │ └── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── softlayer/ │ │ │ ├── SoftLayerApi.java │ │ │ ├── SoftLayerApiMetadata.java │ │ │ ├── SoftLayerProviderMetadata.java │ │ │ ├── binders/ │ │ │ │ ├── NotesToJson.java │ │ │ │ ├── TagToJson.java │ │ │ │ └── VirtualGuestToJson.java │ │ │ ├── compute/ │ │ │ │ ├── config/ │ │ │ │ │ └── SoftLayerComputeServiceContextModule.java │ │ │ │ ├── functions/ │ │ │ │ │ ├── DatacenterToLocation.java │ │ │ │ │ ├── OperatingSystemToImage.java │ │ │ │ │ ├── VirtualGuestToHardware.java │ │ │ │ │ ├── VirtualGuestToImage.java │ │ │ │ │ ├── VirtualGuestToNodeMetadata.java │ │ │ │ │ └── internal/ │ │ │ │ │ └── OperatingSystems.java │ │ │ │ ├── options/ │ │ │ │ │ └── SoftLayerTemplateOptions.java │ │ │ │ └── strategy/ │ │ │ │ └── SoftLayerComputeServiceAdapter.java │ │ │ ├── config/ │ │ │ │ ├── SoftLayerHttpApiModule.java │ │ │ │ └── SoftLayerParserModule.java │ │ │ ├── domain/ │ │ │ │ ├── Address.java │ │ │ │ ├── ContainerVirtualGuestConfiguration.java │ │ │ │ ├── ContainerVirtualGuestConfigurationOption.java │ │ │ │ ├── Datacenter.java │ │ │ │ ├── Network.java │ │ │ │ ├── NetworkVlan.java │ │ │ │ ├── OperatingSystem.java │ │ │ │ ├── Password.java │ │ │ │ ├── PowerState.java │ │ │ │ ├── ProductItem.java │ │ │ │ ├── ProductItemPrice.java │ │ │ │ ├── Region.java │ │ │ │ ├── SecuritySshKey.java │ │ │ │ ├── SoftwareDescription.java │ │ │ │ ├── SoftwareLicense.java │ │ │ │ ├── Subnet.java │ │ │ │ ├── Tag.java │ │ │ │ ├── TagReference.java │ │ │ │ ├── TagType.java │ │ │ │ ├── VirtualDiskImage.java │ │ │ │ ├── VirtualDiskImageSoftware.java │ │ │ │ ├── VirtualGuest.java │ │ │ │ ├── VirtualGuestAttribute.java │ │ │ │ ├── VirtualGuestBlockDevice.java │ │ │ │ ├── VirtualGuestBlockDeviceTemplate.java │ │ │ │ ├── VirtualGuestBlockDeviceTemplateGroup.java │ │ │ │ ├── VirtualGuestNetworkComponent.java │ │ │ │ └── internal/ │ │ │ │ ├── BlockDevice.java │ │ │ │ ├── BlockDeviceTemplateGroup.java │ │ │ │ ├── Datacenter.java │ │ │ │ ├── NetworkComponent.java │ │ │ │ ├── NetworkVlan.java │ │ │ │ ├── PrimaryBackendNetworkComponent.java │ │ │ │ ├── PrimaryNetworkComponent.java │ │ │ │ └── TemplateObject.java │ │ │ ├── features/ │ │ │ │ ├── AccountApi.java │ │ │ │ ├── DatacenterApi.java │ │ │ │ ├── NetworkApi.java │ │ │ │ ├── SoftwareDescriptionApi.java │ │ │ │ ├── VirtualGuestApi.java │ │ │ │ └── VirtualGuestBlockDeviceTemplateGroupApi.java │ │ │ ├── handlers/ │ │ │ │ └── SoftLayerErrorHandler.java │ │ │ └── reference/ │ │ │ └── SoftLayerConstants.java │ │ └── test/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── softlayer/ │ │ │ ├── SoftLayerProviderTest.java │ │ │ ├── binders/ │ │ │ │ ├── NotesToJsonTest.java │ │ │ │ ├── TagToJsonTest.java │ │ │ │ └── VirtualGuestToJsonTest.java │ │ │ ├── compute/ │ │ │ │ ├── SoftLayerComputeServiceAdapterLiveTest.java │ │ │ │ ├── SoftLayerComputeServiceContextLiveTest.java │ │ │ │ ├── SoftLayerComputeServiceLiveTest.java │ │ │ │ ├── SoftLayerTemplateBuilderLiveTest.java │ │ │ │ ├── functions/ │ │ │ │ │ ├── DatacenterToLocationTest.java │ │ │ │ │ ├── OperatingSystemToImageTest.java │ │ │ │ │ ├── VirtualGuestToHardwareTest.java │ │ │ │ │ ├── VirtualGuestToImageTest.java │ │ │ │ │ ├── VirtualGuestToNodeMetadataTest.java │ │ │ │ │ └── internal/ │ │ │ │ │ └── OperatingSystemsTest.java │ │ │ │ └── options/ │ │ │ │ └── SoftLayerTemplateOptionsTest.java │ │ │ ├── domain/ │ │ │ │ ├── AddressTest.java │ │ │ │ └── ContainerVirtualGuestConfigurationTest.java │ │ │ ├── features/ │ │ │ │ ├── AccountApiLiveTest.java │ │ │ │ ├── AccountApiMockTest.java │ │ │ │ ├── BaseSoftLayerApiExpectTest.java │ │ │ │ ├── BaseSoftLayerApiLiveTest.java │ │ │ │ ├── DatacenterApiLiveTest.java │ │ │ │ ├── DatacenterApiMockTest.java │ │ │ │ ├── NetworkApiLiveTest.java │ │ │ │ ├── NetworkApiMockTest.java │ │ │ │ ├── SoftwareDescriptionApiLiveTest.java │ │ │ │ ├── SoftwareDescriptionApiMockTest.java │ │ │ │ ├── VirtualGuestApiLiveTest.java │ │ │ │ ├── VirtualGuestApiMockTest.java │ │ │ │ ├── VirtualGuestBlockDeviceTemplateGroupApiLiveTest.java │ │ │ │ └── VirtualGuestBlockDeviceTemplateGroupApiMockTest.java │ │ │ ├── handlers/ │ │ │ │ └── SoftLayerErrorHandlerTest.java │ │ │ ├── internal/ │ │ │ │ ├── BaseSoftLayerMockTest.java │ │ │ │ └── BaseSoftLayerParseTest.java │ │ │ └── parse/ │ │ │ ├── CreateVirtualGuestResponseTest.java │ │ │ ├── DatacenterParseTest.java │ │ │ ├── DatacentersParseTest.java │ │ │ ├── GetCreateObjectOptionsParseTest.java │ │ │ ├── PublicImagesParseTest.java │ │ │ ├── SoftwareDescriptionsParseTest.java │ │ │ ├── VirtualGuestBlockDeviceTemplateGroupParseTest.java │ │ │ ├── VirtualGuestBlockDeviceTemplateGroupsParseTest.java │ │ │ ├── VirtualGuestFilteredParseTest.java │ │ │ ├── VirtualGuestParseTest.java │ │ │ └── VirtualGuestsParseTest.java │ │ └── resources/ │ │ ├── account_get_block_devices_template_groups.json │ │ ├── account_list.json │ │ ├── container_virtual_guest_configuration.json │ │ ├── datacenter_get.json │ │ ├── datacenter_list.json │ │ ├── logback-test.xml │ │ ├── network_createObject.json │ │ ├── network_createSubnet.json │ │ ├── network_get_153001.json │ │ ├── network_list.json │ │ ├── network_subnet_get_1592631.json │ │ ├── software_description_list.json │ │ ├── virtual_guest_block_device_template_group_get.json │ │ ├── virtual_guest_block_device_template_group_get_public_images.json │ │ ├── virtual_guest_create.json │ │ ├── virtual_guest_create_response.json │ │ ├── virtual_guest_get.json │ │ ├── virtual_guest_get_filtered.json │ │ ├── virtual_guest_set_notes.json │ │ ├── virtual_guest_set_tags.json │ │ └── virtual_guest_set_tags_response.json │ └── ultradns-ws/ │ ├── bnd.bnd │ ├── pom.xml │ └── src/ │ ├── main/ │ │ └── java/ │ │ └── org/ │ │ └── jclouds/ │ │ └── ultradns/ │ │ └── ws/ │ │ ├── UltraDNSWSApi.java │ │ ├── UltraDNSWSApiMetadata.java │ │ ├── UltraDNSWSError.java │ │ ├── UltraDNSWSExceptions.java │ │ ├── UltraDNSWSProviderMetadata.java │ │ ├── UltraDNSWSResponseException.java │ │ ├── binders/ │ │ │ ├── DirectionalGroupCoordinatesToXML.java │ │ │ ├── DirectionalRecordAndGeoGroupToXML.java │ │ │ ├── UpdateDirectionalDNSGroupToXML.java │ │ │ ├── UpdatePoolRecordToXML.java │ │ │ └── ZoneAndResourceRecordToXML.java │ │ ├── config/ │ │ │ └── UltraDNSWSHttpApiModule.java │ │ ├── domain/ │ │ │ ├── AccountLevelGroup.java │ │ │ ├── DirectionalGroup.java │ │ │ ├── DirectionalGroupCoordinates.java │ │ │ ├── DirectionalPool.java │ │ │ ├── DirectionalPoolRecord.java │ │ │ ├── DirectionalPoolRecordDetail.java │ │ │ ├── IdAndName.java │ │ │ ├── PoolRecordSpec.java │ │ │ ├── ResourceRecord.java │ │ │ ├── ResourceRecordDetail.java │ │ │ ├── RoundRobinPool.java │ │ │ ├── Task.java │ │ │ ├── TrafficControllerPool.java │ │ │ ├── TrafficControllerPoolRecord.java │ │ │ ├── TrafficControllerPoolRecordDetail.java │ │ │ ├── UpdatePoolRecord.java │ │ │ ├── Zone.java │ │ │ └── ZoneProperties.java │ │ ├── features/ │ │ │ ├── DirectionalGroupApi.java │ │ │ ├── DirectionalPoolApi.java │ │ │ ├── ResourceRecordApi.java │ │ │ ├── RoundRobinPoolApi.java │ │ │ ├── TaskApi.java │ │ │ ├── TrafficControllerPoolApi.java │ │ │ └── ZoneApi.java │ │ ├── filters/ │ │ │ └── SOAPWrapWithPasswordAuth.java │ │ ├── handlers/ │ │ │ └── UltraDNSWSErrorHandler.java │ │ ├── internal/ │ │ │ ├── DirectionalPoolRecordTypeToString.java │ │ │ ├── RoundRobinPoolRecordTypeToString.java │ │ │ └── TrafficControllerPoolRecordTypeToString.java │ │ ├── predicates/ │ │ │ ├── DirectionalPoolPredicates.java │ │ │ ├── TrafficControllerPoolPredicates.java │ │ │ └── ZonePredicates.java │ │ └── xml/ │ │ ├── AccountHandler.java │ │ ├── AccountLevelGroupsHandler.java │ │ ├── AttributeHandler.java │ │ ├── DirectionalGroupHandler.java │ │ ├── DirectionalPoolListHandler.java │ │ ├── DirectionalPoolRecordDetailHandler.java │ │ ├── DirectionalPoolRecordDetailListHandler.java │ │ ├── ElementTextHandler.java │ │ ├── ItemListHandler.java │ │ ├── PoolRecordSpecHandler.java │ │ ├── RegionListHandler.java │ │ ├── ResourceRecordDetailHandler.java │ │ ├── ResourceRecordListHandler.java │ │ ├── RoundRobinPoolHandler.java │ │ ├── RoundRobinPoolListHandler.java │ │ ├── TaskHandler.java │ │ ├── TaskListHandler.java │ │ ├── TrafficControllerPoolHandler.java │ │ ├── TrafficControllerPoolListHandler.java │ │ ├── TrafficControllerPoolRecordDetailListHandler.java │ │ ├── UltraWSExceptionHandler.java │ │ ├── ZoneHandler.java │ │ ├── ZoneListHandler.java │ │ └── ZonePropertiesHandler.java │ └── test/ │ ├── java/ │ │ └── org/ │ │ └── jclouds/ │ │ └── ultradns/ │ │ └── ws/ │ │ ├── UltraDNSWSApiExpectTest.java │ │ ├── UltraDNSWSApiLiveTest.java │ │ ├── UltraDNSWSProviderMetadataTest.java │ │ ├── binders/ │ │ │ └── ZoneAndResourceRecordToXMLTest.java │ │ ├── features/ │ │ │ ├── DirectionalGroupApiExpectTest.java │ │ │ ├── DirectionalGroupApiLiveTest.java │ │ │ ├── DirectionalPoolApiExpectTest.java │ │ │ ├── DirectionalPoolApiLiveTest.java │ │ │ ├── ResourceRecordApiExpectTest.java │ │ │ ├── ResourceRecordApiLiveTest.java │ │ │ ├── RoundRobinPoolApiExpectTest.java │ │ │ ├── RoundRobinPoolApiLiveTest.java │ │ │ ├── TaskApiExpectTest.java │ │ │ ├── TaskApiLiveTest.java │ │ │ ├── TrafficControllerPoolApiExpectTest.java │ │ │ ├── TrafficControllerPoolApiLiveTest.java │ │ │ ├── ZoneApiExpectTest.java │ │ │ └── ZoneApiLiveTest.java │ │ ├── handlers/ │ │ │ └── UltraDNSWSErrorHandlerTest.java │ │ ├── internal/ │ │ │ ├── BaseDirectionalApiLiveTest.java │ │ │ ├── BaseUltraDNSWSApiExpectTest.java │ │ │ ├── BaseUltraDNSWSApiLiveTest.java │ │ │ └── BaseUltraDNSWSExpectTest.java │ │ ├── parse/ │ │ │ ├── GetAccountLevelDirectionalGroupsResponseTest.java │ │ │ ├── GetAccountsListOfUserResponseTest.java │ │ │ ├── GetAllTasksResponseTest.java │ │ │ ├── GetAvailableGroupsResponseTest.java │ │ │ ├── GetAvailableRegionsResponseTest.java │ │ │ ├── GetDirectionalDNSGroupDetailsResponseTest.java │ │ │ ├── GetDirectionalDNSRecordsForHostResponseTest.java │ │ │ ├── GetDirectionalPoolsByZoneResponseTest.java │ │ │ ├── GetGeneralPropertiesForZoneResponseTest.java │ │ │ ├── GetPoolForPoolHostNameResponseTest.java │ │ │ ├── GetPoolRecordSpecResponseTest.java │ │ │ ├── GetRRLoadBalancingPoolsByZoneResponseTest.java │ │ │ ├── GetResourceRecordsOfDNameByTypeResponseTest.java │ │ │ ├── GetResourceRecordsOfResourceRecordResponseTest.java │ │ │ ├── GetStatusForTaskResponseResponseTest.java │ │ │ ├── GetTCLoadBalancingPoolsByZoneResponseTest.java │ │ │ ├── GetTCPoolRecordsResponseTest.java │ │ │ ├── GetZonesOfAccountResponseTest.java │ │ │ ├── RunTestResponseTest.java │ │ │ ├── TaskNotFoundTest.java │ │ │ └── UltraWSExceptionTest.java │ │ └── predicates/ │ │ ├── DirectionalPoolPredicatesTest.java │ │ ├── TrafficControllerPoolPredicatesTest.java │ │ └── ZonePredicatesTest.java │ └── resources/ │ ├── account.xml │ ├── account_doesnt_exist.xml │ ├── accountlevelgroup_records.xml │ ├── accountlevelgroups.xml │ ├── clear_task.xml │ ├── create_directionalpool.xml │ ├── create_directionalrecord.xml │ ├── create_directionalrecord_existinggroup.xml │ ├── create_directionalrecord_newgroup.xml │ ├── create_rr.xml │ ├── create_rrpool_a.xml │ ├── create_rrpool_aaaa.xml │ ├── create_tcpool.xml │ ├── create_tcrecord.xml │ ├── create_tcrecord_weight.xml │ ├── create_zone.xml │ ├── delete_directionalrecord.xml │ ├── delete_lbpool.xml │ ├── delete_rr.xml │ ├── delete_tcrecord.xml │ ├── delete_zone.xml │ ├── directionalgroup.xml │ ├── directionalgroup_doesnt_exist.xml │ ├── directionalgroup_names.xml │ ├── directionalgroup_overlap.xml │ ├── directionalpool_already_exists.xml │ ├── directionalpool_created.xml │ ├── directionalpool_deleted.xml │ ├── directionalpool_doesnt_exist.xml │ ├── directionalpools.xml │ ├── directionalrecord_already_exists.xml │ ├── directionalrecord_created.xml │ ├── directionalrecord_deleted.xml │ ├── directionalrecord_doesnt_exist.xml │ ├── directionalrecord_updated.xml │ ├── directionalrecords.xml │ ├── get_current_account.xml │ ├── get_directionalgroup.xml │ ├── get_poolrecordspec.xml │ ├── get_task.xml │ ├── get_tcpool_by_dname.xml │ ├── get_zone.xml │ ├── group_doesnt_exist.xml │ ├── lbpool_already_exists.xml │ ├── lbpool_deleted.xml │ ├── lbpool_doesnt_exist.xml │ ├── list_accountlevelgroup_records.xml │ ├── list_accountlevelgroups.xml │ ├── list_directionalgroup_names.xml │ ├── list_directionalgroup_records.xml │ ├── list_directionalpools.xml │ ├── list_directionalrecords.xml │ ├── list_records.xml │ ├── list_records_by_name.xml │ ├── list_records_by_name_and_type.xml │ ├── list_regions.xml │ ├── list_rrpools.xml │ ├── list_rrrecords.xml │ ├── list_tasks.xml │ ├── list_tcpools.xml │ ├── list_tcrecords.xml │ ├── list_zones_by_account.xml │ ├── list_zones_by_account_and_type.xml │ ├── logback.xml │ ├── poolrecord_updated.xml │ ├── poolrecordspec.xml │ ├── records.xml │ ├── records_by_name_and_type.xml │ ├── regions.xml │ ├── rr_already_exists.xml │ ├── rr_created.xml │ ├── rr_deleted.xml │ ├── rr_doesnt_exist.xml │ ├── rr_updated.xml │ ├── rrpool_created.xml │ ├── rrpools.xml │ ├── run_test.xml │ ├── server_fault.xml │ ├── task.xml │ ├── task_doesnt_exist.xml │ ├── taskid.xml │ ├── tasks.xml │ ├── tcpool_created.xml │ ├── tcpool_name.xml │ ├── tcpools.xml │ ├── tcrecord_already_exists.xml │ ├── tcrecord_created.xml │ ├── tcrecord_deleted.xml │ ├── tcrecord_doesnt_exist.xml │ ├── tcrecords.xml │ ├── update_directionalrecord.xml │ ├── update_directionalrecord_group.xml │ ├── update_poolrecord.xml │ ├── update_rr.xml │ ├── zone_already_exists.xml │ ├── zone_created.xml │ ├── zone_deleted.xml │ ├── zone_doesnt_exist.xml │ ├── zoneproperties.xml │ └── zones.xml ├── resources/ │ ├── checkstyle-suppressions.xml │ ├── checkstyle.xml │ ├── modernizer_exclusions.txt │ └── pom.xml ├── scriptbuilder/ │ ├── bnd.bnd │ ├── pom.xml │ └── src/ │ ├── main/ │ │ ├── java/ │ │ │ └── org/ │ │ │ └── jclouds/ │ │ │ └── scriptbuilder/ │ │ │ ├── EnvBuilder.java │ │ │ ├── ExitInsteadOfReturn.java │ │ │ ├── InitScript.java │ │ │ ├── ScriptBuilder.java │ │ │ ├── domain/ │ │ │ │ ├── AcceptsStatementVisitor.java │ │ │ │ ├── AdminAccessVisitor.java │ │ │ │ ├── AppendFile.java │ │ │ │ ├── Call.java │ │ │ │ ├── CreateOrOverwriteFile.java │ │ │ │ ├── CreateRunScript.java │ │ │ │ ├── GitRepoAndRef.java │ │ │ │ ├── InitMetadata.java │ │ │ │ ├── InterpretableStatement.java │ │ │ │ ├── JavaInitMetadata.java │ │ │ │ ├── Kill.java │ │ │ │ ├── LiteralStatement.java │ │ │ │ ├── OsFamily.java │ │ │ │ ├── PipeHttpResponseTo.java │ │ │ │ ├── PipeHttpResponseToBash.java │ │ │ │ ├── PipeHttpResponseToTarxpzfIntoDirectory.java │ │ │ │ ├── SaveHttpResponseTo.java │ │ │ │ ├── ShellToken.java │ │ │ │ ├── Statement.java │ │ │ │ ├── StatementList.java │ │ │ │ ├── StatementVisitor.java │ │ │ │ ├── Statements.java │ │ │ │ ├── StoppableJavaInitMetadata.java │ │ │ │ ├── SwitchArg.java │ │ │ │ ├── UnzipHttpResponseIntoDirectory.java │ │ │ │ └── chef/ │ │ │ │ ├── DataBag.java │ │ │ │ ├── Role.java │ │ │ │ └── RunList.java │ │ │ ├── functionloader/ │ │ │ │ ├── BasicFunctionLoader.java │ │ │ │ ├── CurrentFunctionLoader.java │ │ │ │ ├── FunctionLoader.java │ │ │ │ ├── FunctionNotFoundException.java │ │ │ │ ├── filters/ │ │ │ │ │ └── LicenseHeaderFilter.java │ │ │ │ └── osgi/ │ │ │ │ ├── Activator.java │ │ │ │ ├── BundleFunctionLoader.java │ │ │ │ └── ServiceFunctionLoader.java │ │ │ ├── functions/ │ │ │ │ ├── CredentialsFromAdminAccess.java │ │ │ │ └── InitAdminAccess.java │ │ │ ├── statements/ │ │ │ │ ├── chef/ │ │ │ │ │ ├── ChefSolo.java │ │ │ │ │ ├── InstallChefGems.java │ │ │ │ │ └── InstallChefUsingOmnibus.java │ │ │ │ ├── git/ │ │ │ │ │ ├── CloneGitRepo.java │ │ │ │ │ └── InstallGit.java │ │ │ │ ├── java/ │ │ │ │ │ └── InstallJDK.java │ │ │ │ ├── login/ │ │ │ │ │ ├── AdminAccess.java │ │ │ │ │ ├── AdminAccessBuilderSpec.java │ │ │ │ │ ├── ReplaceShadowPasswordEntry.java │ │ │ │ │ ├── ReplaceShadowPasswordEntryOfLoginUser.java │ │ │ │ │ ├── ShadowStatements.java │ │ │ │ │ ├── SudoStatements.java │ │ │ │ │ ├── Sudoers.java │ │ │ │ │ └── UserAdd.java │ │ │ │ ├── ruby/ │ │ │ │ │ ├── InstallRuby.java │ │ │ │ │ └── InstallRubyGems.java │ │ │ │ └── ssh/ │ │ │ │ ├── AuthorizeRSAPublicKeys.java │ │ │ │ ├── InstallRSAPrivateKey.java │ │ │ │ ├── SshStatements.java │ │ │ │ └── SshdConfig.java │ │ │ └── util/ │ │ │ └── Utils.java │ │ └── resources/ │ │ └── functions/ │ │ ├── .gitattributes │ │ ├── abort.cmd │ │ ├── abort.sh │ │ ├── findPid.cmd │ │ ├── findPid.sh │ │ ├── forget.cmd │ │ ├── forget.sh │ │ ├── installGit.sh │ │ ├── installJDKFromURL.sh │ │ ├── installOpenJDK.sh │ │ ├── installRuby.sh │ │ ├── nextMinute.cmd │ │ ├── setupPublicCurl.sh │ │ ├── sourceEnvFile.cmd │ │ ├── sourceEnvFile.sh │ │ ├── stop.cmd │ │ ├── validateEnvFile.cmd │ │ └── validateEnvFile.sh │ └── test/ │ ├── java/ │ │ └── org/ │ │ └── jclouds/ │ │ └── scriptbuilder/ │ │ ├── EnvBuilderTest.java │ │ ├── InitScriptTest.java │ │ ├── ScriptBuilderTest.java │ │ ├── domain/ │ │ │ ├── AppendFileTest.java │ │ │ ├── CallTest.java │ │ │ ├── CreateOrOverwriteFileTest.java │ │ │ ├── CreateRunScriptTest.java │ │ │ ├── PipeHttpResponseToTest.java │ │ │ ├── SaveHttpResponseToTest.java │ │ │ ├── ShellTokenTest.java │ │ │ ├── StatementListTest.java │ │ │ ├── StatementsTest.java │ │ │ ├── SwitchArgTest.java │ │ │ ├── UnzipHttpResponseIntoDirectoryToTest.java │ │ │ └── chef/ │ │ │ ├── RoleTest.java │ │ │ └── RunListTest.java │ │ ├── functions/ │ │ │ ├── CredentialsFromAdminAccessTest.java │ │ │ └── InitAdminAccessTest.java │ │ ├── statements/ │ │ │ ├── chef/ │ │ │ │ ├── ChefSoloTest.java │ │ │ │ ├── InstallChefGemsTest.java │ │ │ │ └── InstallChefUsingOmnibusTest.java │ │ │ ├── git/ │ │ │ │ ├── CloneGitRepoTest.java │ │ │ │ └── InstallGitTest.java │ │ │ ├── java/ │ │ │ │ └── InstallJDKTest.java │ │ │ ├── login/ │ │ │ │ ├── AdminAccessBuilderSpecTest.java │ │ │ │ ├── AdminAccessTest.java │ │ │ │ ├── ReplaceShadowPasswordEntryOfLoginUserTest.java │ │ │ │ ├── ReplaceShadowPasswordEntryTest.java │ │ │ │ ├── SudoStatementsTest.java │ │ │ │ ├── TestConfiguration.java │ │ │ │ └── UserAddTest.java │ │ │ ├── ruby/ │ │ │ │ ├── InstallRubyGemsTest.java │ │ │ │ └── InstallRubyTest.java │ │ │ └── ssh/ │ │ │ ├── AuthorizeRSAPublicKeyTest.java │ │ │ ├── InstallRSAPrivateKeyTest.java │ │ │ └── SshStatementsTest.java │ │ └── util/ │ │ └── UtilsTest.java │ └── resources/ │ ├── .gitattributes │ ├── client_rb_append.cmd │ ├── client_rb_append.sh │ ├── client_rb_overwrite.cmd │ ├── client_rb_overwrite.sh │ ├── forget.cmd │ ├── functions/ │ │ ├── .gitattributes │ │ ├── nonewline.cmd │ │ ├── nonewline.sh │ │ └── test_install_jdk_from_url.sh │ ├── test │ ├── test_adminaccess_flipped.sh │ ├── test_adminaccess_params.sh │ ├── test_adminaccess_params_and_fullname.sh │ ├── test_adminaccess_plainuser.sh │ ├── test_adminaccess_standard.sh │ ├── test_ebs.sh │ ├── test_env.cmd │ ├── test_env.sh │ ├── test_find_pid.cmd │ ├── test_find_pid.sh │ ├── test_init.sh │ ├── test_init_script.sh │ ├── test_install_chef_gems_scriptbuilder.sh │ ├── test_install_chef_omnibus_scriptbuilder.sh │ ├── test_install_chef_version_omnibus_scriptbuilder.sh │ ├── test_install_git_scriptbuilder.sh │ ├── test_install_jdk_scriptbuilder.sh │ ├── test_install_ruby.sh │ ├── test_install_ruby_scriptbuilder.sh │ ├── test_install_rubygems.sh │ ├── test_install_rubygems_scriptbuilder.sh │ ├── test_runrun.sh │ ├── test_runrun_header.sh │ ├── test_script.cmd │ ├── test_script.sh │ ├── test_seek_and_destroy.cmd │ └── test_seek_and_destroy.sh └── skeletons/ ├── pom.xml └── standalone-compute/ ├── README.txt ├── bnd.bnd ├── pom.xml └── src/ ├── main/ │ └── java/ │ └── org/ │ └── jclouds/ │ └── servermanager/ │ ├── Datacenter.java │ ├── Hardware.java │ ├── Image.java │ ├── Server.java │ ├── ServerManager.java │ ├── ServerManagerApiMetadata.java │ └── compute/ │ ├── config/ │ │ └── ServerManagerComputeServiceContextModule.java │ ├── functions/ │ │ ├── DatacenterToLocation.java │ │ ├── ServerManagerHardwareToHardware.java │ │ ├── ServerManagerImageToImage.java │ │ └── ServerToNodeMetadata.java │ └── strategy/ │ └── ServerManagerComputeServiceAdapter.java └── test/ ├── java/ │ └── org/ │ └── jclouds/ │ └── servermanager/ │ └── compute/ │ ├── ServerManagerComputeServiceContextBuilderTest.java │ ├── ServerManagerComputeServiceLiveTest.java │ └── ServerManagerExperimentLiveTest.java └── resources/ └── log4j.xml ================================================ FILE CONTENTS ================================================ ================================================ FILE: .asf.yaml ================================================ # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. github: description: The Java Multi-Cloud Toolkit homepage: https://jclouds.apache.org/ labels: - java - library - cloud - jclouds # Uncomment the following lines if at some point we feel like # we want to control merges and pull request builds. # # enabled_merge_buttons: # squash: true # merge: false # rebase: false # protected_branches: # master: # required_status_checks: # contexts: # - build # required_pull_request_reviews: # required_approving_review_count: 1 ================================================ FILE: .dir-locals.el ================================================ ;; Licensed to the Apache Software Foundation (ASF) under one or more ;; contributor license agreements. See the NOTICE file distributed with ;; this work for additional information regarding copyright ownership. ;; The ASF licenses this file to You under the Apache License, Version 2.0 ;; (the "License"); you may not use this file except in compliance with ;; the License. You may obtain a copy of the License at ;; ;; http://www.apache.org/licenses/LICENSE-2.0 ;; ;; Unless required by applicable law or agreed to in writing, software ;; distributed under the License is distributed on an "AS IS" BASIS, ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ;; See the License for the specific language governing permissions and ;; limitations under the License. ((nil . ((c-basic-offset . 3)))) ================================================ FILE: .gitattributes ================================================ * text eol=lf *.cmd binary ================================================ FILE: .github/workflows/ci.yaml ================================================ # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. name: CI on: push: branches: - master pull_request: branches: - master jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-java@v4 with: java-version: "11" distribution: temurin cache: maven - name: Build run: mvn clean verify checkstyle:checkstyle -B -q -Dorg.slf4j.simpleLogger.defaultLogLevel=ERROR -Pdoc,src ================================================ FILE: .gitignore ================================================ # use glob syntax. syntax: glob target/ test-output/ bin/ .settings/ .classpath .project .idea/ *.iml *.eml *.ipr *.iws *.DS_STORE TAGS .metadata/ atlassian-ide-plugin.xml .DS_Store .java-version .factorypath .apt_generated .apt_generated_tests .checkstyle nb-configuration.xml nbactions.xml /.nb-gradle/ dependency-reduced-pom.xml .vscode ================================================ FILE: .mailmap ================================================ Adrian Cole Adrian Cole Adrian Cole Adrian Cole Adrian Cole Alex Yarmula Alfredo Morresi Alfredo Morresi Andrea Turli Andrea Turli Andrea Turli Andrea Turli Andrea Turli Andrei Savu Andrew Phillips Antoni Batchelli Barak Merimovich Carlos Sanchez Dan Lo Bianco Dmitry Durnev Hans Hrasna Hunter Hutchinson Ilja Bobkevic Ivan Meredith James Murty Karthik Ganesan Nicholas Terry Nirmal Fernando Seshu Pasam Shane Witbeck Tibor Kiss Victor Galkin Vijay Kiran Zack Shoylev ================================================ FILE: CONTRIBUTING.md ================================================ Please review the [How to Contribute](https://cwiki.apache.org/confluence/display/JCLOUDS/Contribute) page for information on how to submit your patch and how the review process works. Also make sure all the changes are aligned with the [Coding Standards](https://cwiki.apache.org/confluence/display/JCLOUDS/Writing+jclouds+Code) of the project. Thanks! The Apache jclouds team ================================================ FILE: README.md ================================================ jclouds ====== Apache jclouds is an open source multi-cloud toolkit for the Java platform that gives you the freedom to create applications that are portable across clouds while giving you full control to use cloud-specific features. For more information about using or contributing to jclouds, please visit our website at [jclouds.apache.org](http://jclouds.apache.org/). License ------- Copyright (C) 2009-2022 The Apache Software Foundation Licensed under the Apache License, Version 2.0 ================================================ FILE: all/pom.xml ================================================ 4.0.0 org.apache.jclouds jclouds-project 2.7.1-SNAPSHOT ../project/pom.xml jclouds-all all org.apache.jclouds.api rackspace-cloudidentity ${project.version} org.apache.jclouds.api openstack-cinder ${project.version} org.apache.jclouds.api rackspace-clouddns ${project.version} org.apache.jclouds.provider aws-cloudwatch ${project.version} org.apache.jclouds.provider rackspace-cloudblockstorage-us ${project.version} org.apache.jclouds.provider rackspace-cloudblockstorage-uk ${project.version} org.apache.jclouds.provider rackspace-clouddns-us ${project.version} org.apache.jclouds.provider rackspace-clouddns-uk ${project.version} org.apache.jclouds.provider rackspace-clouddatabases-us ${project.version} org.apache.jclouds.provider rackspace-clouddatabases-uk ${project.version} org.apache.jclouds.provider aws-sqs ${project.version} org.apache.jclouds.provider aws-sts ${project.version} org.apache.jclouds.provider aws-route53 ${project.version} org.apache.jclouds.provider ultradns-ws ${project.version} org.apache.jclouds.provider dynect ${project.version} org.apache.jclouds.api chef ${project.version} ${project.groupId} jclouds-allloadbalancer ${project.version} ${project.groupId} jclouds-allcompute ${project.version} ${project.groupId} jclouds-allblobstore ${project.version} ================================================ FILE: allblobstore/pom.xml ================================================ 4.0.0 org.apache.jclouds jclouds-project 2.7.1-SNAPSHOT ../project/pom.xml jclouds-allblobstore allblobstore org.apache.jclouds.api s3 ${project.version} org.apache.jclouds.provider aws-s3 ${project.version} org.apache.jclouds.provider azureblob ${project.version} org.apache.jclouds.api atmos ${project.version} org.apache.jclouds.provider b2 ${project.version} org.apache.jclouds.api glacier ${project.version} org.apache.jclouds.provider google-cloud-storage ${project.version} org.apache.jclouds.api openstack-swift ${project.version} org.apache.jclouds.provider rackspace-cloudfiles-us ${project.version} org.apache.jclouds.provider rackspace-cloudfiles-uk ${project.version} ================================================ FILE: allcompute/pom.xml ================================================ 4.0.0 org.apache.jclouds jclouds-project 2.7.1-SNAPSHOT ../project/pom.xml jclouds-allcompute allcompute org.apache.jclouds.provider aws-ec2 ${project.version} org.apache.jclouds.api openstack-nova ${project.version} org.apache.jclouds.api openstack-nova-ec2 ${project.version} org.apache.jclouds.api byon ${project.version} org.apache.jclouds.api ec2 ${project.version} org.apache.jclouds.provider gogrid ${project.version} org.apache.jclouds.api elasticstack ${project.version} org.apache.jclouds.provider elastichosts-lon-p ${project.version} org.apache.jclouds.provider elastichosts-sat-p ${project.version} org.apache.jclouds.provider elastichosts-lon-b ${project.version} org.apache.jclouds.provider openhosting-east1 ${project.version} org.apache.jclouds.provider serverlove-z1-man ${project.version} org.apache.jclouds.provider skalicloud-sdg-my ${project.version} org.apache.jclouds.provider go2cloud-jhb1 ${project.version} org.apache.jclouds.provider softlayer ${project.version} org.apache.jclouds.api cloudstack ${project.version} org.apache.jclouds.provider rackspace-cloudservers-us ${project.version} org.apache.jclouds.provider rackspace-cloudservers-uk ${project.version} org.apache.jclouds.provider google-compute-engine ${project.version} org.apache.jclouds.provider digitalocean2 ${project.version} org.apache.jclouds.provider profitbricks ${project.version} org.apache.jclouds.api docker ${project.version} org.apache.jclouds.provider packet ${project.version} org.apache.jclouds.provider azurecompute-arm ${project.version} ================================================ FILE: allloadbalancer/pom.xml ================================================ 4.0.0 org.apache.jclouds jclouds-project 2.7.1-SNAPSHOT ../project/pom.xml jclouds-allloadbalancer allloadbalancer org.apache.jclouds.provider rackspace-cloudloadbalancers-uk ${project.version} org.apache.jclouds.provider rackspace-cloudloadbalancers-us ${project.version} ================================================ FILE: apis/atmos/README.txt ================================================ # # The jclouds API for EMC's Atmos Online Storage (http://www.emccis.com/). # # TODO: Implementation status. # TODO: Supported features. # TODO: Usage example. ================================================ FILE: apis/atmos/bnd.bnd ================================================ Export-Package: \ org.jclouds.atmos.*;version="${project.version}";-noimport:=true ================================================ FILE: apis/atmos/pom.xml ================================================ 4.0.0 org.apache.jclouds jclouds-project 2.7.1-SNAPSHOT ../../project/pom.xml org.apache.jclouds.api atmos jclouds atmos components https://accesspoint.atmosonline.com 1.3.0 FIXME_IDENTITY FIXME_CREDENTIAL org.apache.jclouds jclouds-blobstore ${project.version} org.apache.jclouds jclouds-blobstore ${project.version} test-jar test org.apache.jclouds jclouds-core ${project.version} test-jar test org.apache.logging.log4j log4j-core test org.apache.jclouds.driver jclouds-log4j ${project.version} test com.google.auto.service auto-service true live org.apache.maven.plugins maven-surefire-plugin integration integration-test test ${jclouds.blobstore.httpstream.url} ${jclouds.blobstore.httpstream.md5} ${test.atmos.endpoint} ${test.atmos.api-version} ${test.atmos.build-version} ${test.atmos.identity} ${test.atmos.credential} ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/AtmosApiMetadata.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos; import static org.jclouds.Constants.PROPERTY_IDEMPOTENT_METHODS; import static org.jclouds.blobstore.reference.BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX; import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS; import static org.jclouds.reflect.Reflection2.typeToken; import java.net.URI; import java.util.Properties; import org.jclouds.apis.ApiMetadata; import org.jclouds.atmos.blobstore.config.AtmosBlobStoreContextModule; import org.jclouds.atmos.config.AtmosHttpApiModule; import org.jclouds.blobstore.BlobStoreContext; import org.jclouds.rest.internal.BaseHttpApiMetadata; import com.google.auto.service.AutoService; import com.google.common.collect.ImmutableSet; import com.google.inject.Module; @AutoService(ApiMetadata.class) public class AtmosApiMetadata extends BaseHttpApiMetadata { private static Builder builder() { return new Builder(); } @Override public Builder toBuilder() { return builder().fromApiMetadata(this); } public AtmosApiMetadata() { this(builder()); } protected AtmosApiMetadata(Builder builder) { super(builder); } public static Properties defaultProperties() { Properties properties = BaseHttpApiMetadata.defaultProperties(); properties.setProperty(PROPERTY_REGIONS, "DEFAULT"); properties.setProperty(PROPERTY_USER_METADATA_PREFIX, "X-Object-Meta-"); properties.setProperty(PROPERTY_IDEMPOTENT_METHODS, "DELETE,GET,HEAD,OPTIONS,POST,PUT"); return properties; } public static class Builder extends BaseHttpApiMetadata.Builder { protected Builder() { super(AtmosClient.class); id("atmos") .name("EMC's Atmos API") .identityName("Subtenant ID (UID)") .credentialName("Shared Secret") .documentation(URI.create("https://community.emc.com/docs/DOC-10508")) .version("1.4.0") .defaultEndpoint("https://accesspoint.atmosonline.com") .defaultProperties(AtmosApiMetadata.defaultProperties()) .view(typeToken(BlobStoreContext.class)) .defaultModules(ImmutableSet.>of(AtmosHttpApiModule.class, AtmosBlobStoreContextModule.class)); } @Override public AtmosApiMetadata build() { return new AtmosApiMetadata(this); } @Override protected Builder self() { return this; } } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/AtmosClient.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos; import static com.google.common.net.HttpHeaders.EXPECT; import java.io.Closeable; import java.net.URI; import jakarta.inject.Named; import jakarta.ws.rs.Consumes; import jakarta.ws.rs.DELETE; import jakarta.ws.rs.GET; import jakarta.ws.rs.HEAD; import jakarta.ws.rs.POST; import jakarta.ws.rs.PUT; import jakarta.ws.rs.Path; import jakarta.ws.rs.PathParam; import jakarta.ws.rs.Produces; import jakarta.ws.rs.core.MediaType; import org.jclouds.Fallbacks.FalseOnNotFoundOr404; import org.jclouds.Fallbacks.NullOnNotFoundOr404; import org.jclouds.atmos.binders.BindMetadataToHeaders; import org.jclouds.atmos.domain.AtmosObject; import org.jclouds.atmos.domain.BoundedSet; import org.jclouds.atmos.domain.DirectoryEntry; import org.jclouds.atmos.domain.SystemMetadata; import org.jclouds.atmos.domain.UserMetadata; import org.jclouds.atmos.fallbacks.TrueOn404FalseOnPathNotEmpty; import org.jclouds.atmos.filters.SignRequest; import org.jclouds.atmos.functions.AtmosObjectName; import org.jclouds.atmos.functions.ParseDirectoryListFromContentAndHeaders; import org.jclouds.atmos.functions.ParseObjectFromHeadersAndHttpContent; import org.jclouds.atmos.functions.ParseSystemMetadataFromHeaders; import org.jclouds.atmos.functions.ParseUserMetadataFromHeaders; import org.jclouds.atmos.functions.ReturnTrueIfGroupACLIsOtherRead; import org.jclouds.atmos.options.ListOptions; import org.jclouds.atmos.options.PutOptions; import org.jclouds.blobstore.BlobStoreFallbacks.NullOnKeyAlreadyExists; import org.jclouds.blobstore.BlobStoreFallbacks.ThrowContainerNotFoundOn404; import org.jclouds.blobstore.BlobStoreFallbacks.ThrowKeyNotFoundOn404; import org.jclouds.http.functions.ParseURIFromListOrLocationHeaderIf20x; import org.jclouds.http.options.GetOptions; import org.jclouds.javax.annotation.Nullable; import org.jclouds.rest.annotations.BinderParam; import org.jclouds.rest.annotations.Fallback; import org.jclouds.rest.annotations.Headers; import org.jclouds.rest.annotations.ParamParser; import org.jclouds.rest.annotations.QueryParams; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.ResponseParser; import com.google.inject.Provides; /** Provides access to EMC Atmos Online Storage resources via their REST API. */ @RequestFilters(SignRequest.class) @Path("/rest/namespace") public interface AtmosClient extends Closeable { @Provides AtmosObject newObject(); @Named("ListDirectory") @GET @Path("/") @ResponseParser(ParseDirectoryListFromContentAndHeaders.class) @Consumes(MediaType.TEXT_XML) BoundedSet listDirectories(ListOptions... options); @Named("ListDirectory") @GET @Path("/{directoryName}/") @ResponseParser(ParseDirectoryListFromContentAndHeaders.class) @Fallback(ThrowContainerNotFoundOn404.class) @Consumes(MediaType.TEXT_XML) @Headers(keys = "x-emc-include-meta", values = "1") BoundedSet listDirectory( @PathParam("directoryName") String directoryName, ListOptions... options); @Named("CreateDirectory") @POST @Path("/{directoryName}/") @Fallback(NullOnKeyAlreadyExists.class) @Produces(MediaType.APPLICATION_OCTET_STREAM) @Consumes(MediaType.WILDCARD) URI createDirectory(@PathParam("directoryName") String directoryName, PutOptions... options); @Nullable @Named("CreateObject") @POST @Path("/{parent}/{name}") @Headers(keys = EXPECT, values = "100-continue") @ResponseParser(ParseURIFromListOrLocationHeaderIf20x.class) @Consumes(MediaType.WILDCARD) URI createFile(@PathParam("parent") String parent, @PathParam("name") @ParamParser(AtmosObjectName.class) @BinderParam(BindMetadataToHeaders.class) AtmosObject object, PutOptions... options); @Named("UpdateObject") @PUT @Path("/{parent}/{name}") @Headers(keys = EXPECT, values = "100-continue") @Fallback(ThrowKeyNotFoundOn404.class) @Consumes(MediaType.WILDCARD) void updateFile(@PathParam("parent") String parent, @PathParam("name") @ParamParser(AtmosObjectName.class) @BinderParam(BindMetadataToHeaders.class) AtmosObject object, PutOptions... options); @Named("ReadObject") @GET @ResponseParser(ParseObjectFromHeadersAndHttpContent.class) @Fallback(NullOnNotFoundOr404.class) @Path("/{path}") @Consumes(MediaType.WILDCARD) AtmosObject readFile(@PathParam("path") String path, GetOptions... options); @Named("GetObjectMetadata") @HEAD @ResponseParser(ParseObjectFromHeadersAndHttpContent.class) @Fallback(NullOnNotFoundOr404.class) @Path("/{path}") @Consumes(MediaType.WILDCARD) AtmosObject headFile(@PathParam("path") String path); @Named("GetSystemMetadata") @HEAD @ResponseParser(ParseSystemMetadataFromHeaders.class) @Fallback(NullOnNotFoundOr404.class) // currently throws 403 errors @QueryParams(keys = "metadata/system") @Path("/{path}") @Consumes(MediaType.WILDCARD) SystemMetadata getSystemMetadata(@PathParam("path") String path); @Named("GetUserMetadata") @HEAD @ResponseParser(ParseUserMetadataFromHeaders.class) @Fallback(NullOnNotFoundOr404.class) @Path("/{path}") @QueryParams(keys = "metadata/user") @Consumes(MediaType.WILDCARD) UserMetadata getUserMetadata(@PathParam("path") String path); @Named("DeleteObject") @DELETE @Fallback(TrueOn404FalseOnPathNotEmpty.class) @Path("/{path}") @Consumes(MediaType.WILDCARD) boolean deletePath(@PathParam("path") String path); @Named("GetObjectMetadata") @HEAD @Fallback(FalseOnNotFoundOr404.class) @Path("/{path}") @Consumes(MediaType.WILDCARD) boolean pathExists(@PathParam("path") String path); @Named("GetObjectMetadata") @HEAD @ResponseParser(ReturnTrueIfGroupACLIsOtherRead.class) @Path("/{path}") @Consumes(MediaType.WILDCARD) @Fallback(FalseOnNotFoundOr404.class) boolean isPublic(@PathParam("path") String path); @Named("SetObjectMetadata") @POST @Path("/{path}") @QueryParams(keys = "acl") @Produces(MediaType.APPLICATION_OCTET_STREAM) @Fallback(ThrowKeyNotFoundOn404.class) @Consumes(MediaType.WILDCARD) void setGroupAcl(@PathParam("path") String path, PutOptions options); } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/AtmosResponseException.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos; import org.jclouds.atmos.domain.AtmosError; import org.jclouds.http.HttpCommand; import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponseException; import org.jclouds.javax.annotation.Nullable; /** * Encapsulates an Error from Atmos Storage Services. * * @see AtmosError * @see ParseAtmosErrorFromXmlContent */ public class AtmosResponseException extends HttpResponseException { private transient AtmosError error; public AtmosResponseException(HttpCommand command, HttpResponse response, AtmosError error) { super(String.format("command %s failed with code %s, error: %s", command.getCurrentRequest() .getRequestLine(), response.getStatusCode(), error.toString()), command, response); this.setError(error); } public AtmosResponseException(HttpCommand command, HttpResponse response, AtmosError error, Throwable cause) { super(String.format("command %1$s failed with error: %2$s", command.getCurrentRequest() .getRequestLine(), error.toString()), command, response, cause); this.setError(error); } public AtmosResponseException(String message, HttpCommand command, HttpResponse response, AtmosError error) { super(message, command, response); this.setError(error); } public AtmosResponseException(String message, HttpCommand command, HttpResponse response, AtmosError error, Throwable cause) { super(message, command, response, cause); this.setError(error); } public void setError(AtmosError error) { this.error = error; } @Nullable public AtmosError getError() { return error; } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/binders/BindMetadataToHeaders.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.binders; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import jakarta.inject.Inject; import jakarta.inject.Singleton; import com.google.common.io.BaseEncoding; import org.jclouds.atmos.domain.AtmosObject; import org.jclouds.atmos.reference.AtmosHeaders; import org.jclouds.http.HttpRequest; import org.jclouds.rest.Binder; @Singleton public class BindMetadataToHeaders implements Binder { private final BindUserMetadataToHeaders metaBinder; @Inject protected BindMetadataToHeaders(BindUserMetadataToHeaders metaBinder) { this.metaBinder = metaBinder; } @Override public R bindToRequest(R request, Object input) { checkArgument(checkNotNull(input, "input") instanceof AtmosObject, "this binder is only valid for AtmosObject!"); checkNotNull(request, "request"); AtmosObject object = AtmosObject.class.cast(input); checkNotNull(object.getPayload(), "object payload"); checkArgument(object.getPayload().getContentMetadata().getContentLength() != null, "contentLength must be set, streaming not supported"); byte[] contentMD5 = object.getContentMetadata().getContentMD5(); if (contentMD5 != null) { request = (R) request.toBuilder() .addHeader(AtmosHeaders.CHECKSUM, "MD5/0/" + BaseEncoding.base16().encode(contentMD5)) .build(); } return metaBinder.bindToRequest(request, object.getUserMetadata()); } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/binders/BindUserMetadataToHeaders.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.binders; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import java.util.Map; import jakarta.inject.Singleton; import org.jclouds.atmos.domain.UserMetadata; import org.jclouds.http.HttpRequest; import org.jclouds.rest.Binder; import com.google.common.base.Function; import com.google.common.base.Joiner; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap.Builder; import com.google.common.collect.Multimaps; @Singleton public class BindUserMetadataToHeaders implements Binder, Function> { @SuppressWarnings("unchecked") @Override public R bindToRequest(R request, Object input) { checkArgument(checkNotNull(input, "input") instanceof UserMetadata, "this binder is only valid for UserMetadatas!"); checkNotNull(request, "request"); return (R) request.toBuilder().replaceHeaders(Multimaps.forMap(apply(UserMetadata.class.cast(input)))).build(); } @Override public Map apply(UserMetadata md) { Builder headers = ImmutableMap.builder(); if (!md.getMetadata().isEmpty()) { String header = Joiner.on(',').withKeyValueSeparator("=").join(md.getMetadata()); headers.put("x-emc-meta", header); } if (!md.getListableMetadata().isEmpty()) { String header = Joiner.on(',').withKeyValueSeparator("=").join(md.getListableMetadata()); headers.put("x-emc-listable-meta", header); } if (!md.getTags().isEmpty()) { String header = Joiner.on(',').join(md.getTags()); headers.put("x-emc-tags", header); } if (!md.getListableTags().isEmpty()) { String header = Joiner.on(',').join(md.getListableTags()); headers.put("x-emc-listable-tags", header); } return headers.build(); } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/blobstore/AtmosBlobRequestSigner.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.blobstore; import static com.google.common.base.Preconditions.checkNotNull; import static org.jclouds.blobstore.util.BlobStoreUtils.cleanRequest; import static org.jclouds.reflect.Reflection2.method; import java.net.URI; import java.util.Date; import jakarta.inject.Inject; import jakarta.inject.Singleton; import org.jclouds.atmos.AtmosClient; import org.jclouds.atmos.blobstore.functions.BlobToObject; import org.jclouds.atmos.domain.AtmosObject; import org.jclouds.atmos.filters.SignRequest; import org.jclouds.atmos.options.PutOptions; import org.jclouds.blobstore.BlobRequestSigner; import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.functions.BlobToHttpGetOptions; import org.jclouds.date.DateService; import org.jclouds.date.TimeStamp; import org.jclouds.domain.Credentials; import org.jclouds.http.HttpRequest; import org.jclouds.http.Uris; import org.jclouds.http.options.GetOptions; import org.jclouds.reflect.Invocation; import com.google.common.base.Function; import com.google.common.base.Supplier; import com.google.common.collect.ImmutableList; import com.google.common.reflect.Invokable; import com.google.inject.Provider; @Singleton public class AtmosBlobRequestSigner implements BlobRequestSigner { private static final int DEFAULT_EXPIRY_SECONDS = 15 * 60; private final Function processor; private final BlobToObject blobToObject; private final BlobToHttpGetOptions blob2ObjectGetOptions; private final Invokable getMethod; private final Invokable deleteMethod; private final Invokable createMethod; private final SignRequest signer; private final URI endpoint; private final String identity; private final DateService dateService; private final Provider timeStampProvider; @Inject public AtmosBlobRequestSigner(Function processor, BlobToObject blobToObject, BlobToHttpGetOptions blob2ObjectGetOptions, SignRequest signer, @org.jclouds.location.Provider Supplier endpointProvider, @org.jclouds.location.Provider Supplier creds, DateService dateService, @TimeStamp Provider timeStampProvider) throws SecurityException, NoSuchMethodException { this.processor = checkNotNull(processor, "processor"); this.blobToObject = checkNotNull(blobToObject, "blobToObject"); this.blob2ObjectGetOptions = checkNotNull(blob2ObjectGetOptions, "blob2ObjectGetOptions"); this.getMethod = method(AtmosClient.class, "readFile", String.class, GetOptions[].class); this.deleteMethod = method(AtmosClient.class, "deletePath", String.class); this.createMethod = method(AtmosClient.class, "createFile", String.class, AtmosObject.class, PutOptions[].class); this.signer = signer; this.endpoint = endpointProvider.get(); this.identity = creds.get().identity; this.dateService = dateService; this.timeStampProvider = timeStampProvider; } @Override public HttpRequest signGetBlob(String container, String name) { return signGetBlob(container, name, DEFAULT_EXPIRY_SECONDS); } @Override public HttpRequest signGetBlob(String container, String name, long timeInSeconds) { checkNotNull(container, "container"); checkNotNull(name, "name"); return sign("GET", "/rest/namespace/" + container + "/" + name, timeInSeconds); } @Override public HttpRequest signPutBlob(String container, Blob blob) { checkNotNull(container, "container"); checkNotNull(blob, "blob"); return cleanRequest(processor.apply(Invocation.create(createMethod, ImmutableList. of(container, blobToObject.apply(blob))))); } @Override public HttpRequest signPutBlob(String container, Blob blob, long timeInSeconds) { throw new UnsupportedOperationException(); } private String getPath(String container, String name) { return checkNotNull(container, "container") + "/" + checkNotNull(name, "name"); } @Override public HttpRequest signGetBlob(String container, String name, org.jclouds.blobstore.options.GetOptions options) { checkNotNull(container, "container"); checkNotNull(name, "name"); return cleanRequest(processor.apply(Invocation.create(getMethod, ImmutableList.of(getPath(container, name), blob2ObjectGetOptions.apply(checkNotNull(options, "options")))))); } private HttpRequest sign(String method, String path, long timeInSeconds) { Date now = dateService.rfc1123DateParse(timeStampProvider.get()); String expires = String.valueOf(now.getTime() / 1000 + timeInSeconds); String stringToSign = method + "\n" + path + "\n" + identity + "\n" + expires; return HttpRequest.builder() .method(method) .endpoint(Uris.uriBuilder(endpoint.getScheme() + "://" + endpoint.getHost()).appendPath(path).build()) .addQueryParam("uid", identity) .addQueryParam("expires", expires) .addQueryParam("signature", signer.calculateSignature(stringToSign)) .build(); } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/blobstore/AtmosBlobStore.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.blobstore; import static com.google.common.base.Preconditions.checkNotNull; import static org.jclouds.atmos.options.PutOptions.Builder.publicRead; import java.io.InputStream; import java.util.List; import java.util.Set; import jakarta.inject.Inject; import jakarta.inject.Provider; import jakarta.inject.Singleton; import org.jclouds.atmos.AtmosClient; import org.jclouds.atmos.blobstore.functions.BlobStoreListOptionsToListOptions; import org.jclouds.atmos.blobstore.functions.BlobToObject; import org.jclouds.atmos.blobstore.functions.DirectoryEntryListToResourceMetadataList; import org.jclouds.atmos.blobstore.functions.ObjectToBlob; import org.jclouds.atmos.blobstore.functions.ObjectToBlobMetadata; import org.jclouds.atmos.options.ListOptions; import org.jclouds.atmos.util.AtmosUtils; import org.jclouds.blobstore.BlobStoreContext; import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.BlobAccess; import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.ContainerAccess; import org.jclouds.blobstore.domain.MultipartPart; import org.jclouds.blobstore.domain.MultipartUpload; import org.jclouds.blobstore.domain.PageSet; import org.jclouds.blobstore.domain.StorageMetadata; import org.jclouds.blobstore.functions.BlobToHttpGetOptions; import org.jclouds.blobstore.internal.BaseBlobStore; import org.jclouds.blobstore.options.CopyOptions; import org.jclouds.blobstore.options.CreateContainerOptions; import org.jclouds.blobstore.options.PutOptions; import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata; import org.jclouds.blobstore.util.BlobUtils; import org.jclouds.collect.Memoized; import org.jclouds.crypto.Crypto; import org.jclouds.domain.Location; import org.jclouds.http.options.GetOptions; import org.jclouds.io.Payload; import org.jclouds.io.PayloadSlicer; import com.google.common.base.Strings; import com.google.common.base.Supplier; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; @Singleton public class AtmosBlobStore extends BaseBlobStore { private final AtmosClient sync; private final ObjectToBlob object2Blob; private final ObjectToBlobMetadata object2BlobMd; private final BlobToObject blob2Object; private final BlobStoreListOptionsToListOptions container2ContainerListOptions; private final DirectoryEntryListToResourceMetadataList container2ResourceList; private final Crypto crypto; private final BlobToHttpGetOptions blob2ObjectGetOptions; private final Provider fetchBlobMetadataProvider; private final LoadingCache isPublic; @Inject AtmosBlobStore(BlobStoreContext context, BlobUtils blobUtils, Supplier defaultLocation, @Memoized Supplier> locations, PayloadSlicer slicer, AtmosClient sync, ObjectToBlob object2Blob, ObjectToBlobMetadata object2BlobMd, BlobToObject blob2Object, BlobStoreListOptionsToListOptions container2ContainerListOptions, DirectoryEntryListToResourceMetadataList container2ResourceList, Crypto crypto, BlobToHttpGetOptions blob2ObjectGetOptions, Provider fetchBlobMetadataProvider, LoadingCache isPublic) { super(context, blobUtils, defaultLocation, locations, slicer); this.blob2ObjectGetOptions = checkNotNull(blob2ObjectGetOptions, "blob2ObjectGetOptions"); this.sync = checkNotNull(sync, "sync"); this.container2ContainerListOptions = checkNotNull(container2ContainerListOptions, "container2ContainerListOptions"); this.container2ResourceList = checkNotNull(container2ResourceList, "container2ResourceList"); this.object2Blob = checkNotNull(object2Blob, "object2Blob"); this.blob2Object = checkNotNull(blob2Object, "blob2Object"); this.object2BlobMd = checkNotNull(object2BlobMd, "object2BlobMd"); this.crypto = checkNotNull(crypto, "crypto"); this.fetchBlobMetadataProvider = checkNotNull(fetchBlobMetadataProvider, "fetchBlobMetadataProvider"); this.isPublic = checkNotNull(isPublic, "isPublic"); } /** * This implementation invokes {@link AtmosClient#headFile} */ @Override public BlobMetadata blobMetadata(String container, String key) { return object2BlobMd.apply(sync.headFile(container + "/" + key)); } /** * This implementation invokes {@link AtmosClient#deletePath} followed by * {@link AtmosClient#pathExists} until it is true. */ protected boolean deleteAndVerifyContainerGone(final String container) { sync.deletePath(container + "/"); return !sync.pathExists(container + "/"); } /** * This implementation invokes {@link AtmosClient#createDirectory} * * @param location * currently ignored * @param container * directory name */ @Override public boolean createContainerInLocation(Location location, String container) { return sync.createDirectory(container) != null; } @Override public ContainerAccess getContainerAccess(String container) { if (sync.isPublic(container)) { return ContainerAccess.PUBLIC_READ; } else { return ContainerAccess.PRIVATE; } } @Override public void setContainerAccess(String container, ContainerAccess access) { org.jclouds.atmos.options.PutOptions options = new org.jclouds.atmos.options.PutOptions(); if (access == ContainerAccess.PUBLIC_READ) { options.publicRead(); } else { options.publicNone(); } sync.setGroupAcl(container, options); } /** * This implementation invokes {@link AtmosClient#createDirectory} * * @param container * directory name */ @Override public void createDirectory(String container, String directory) { sync.createDirectory(container + "/" + directory); } /** * This implementation invokes {@link #removeBlob} */ @Override public void deleteDirectory(String containerName, String directory) { removeBlob(containerName, directory + "/"); } /** * This implementation invokes {@link AtmosClient#pathExists} */ @Override public boolean containerExists(String container) { return sync.pathExists(container + "/"); } /** * This implementation invokes {@link AtmosClient#pathExists} */ @Override public boolean directoryExists(String container, String directory) { return sync.pathExists(container + "/" + directory + "/"); } /** * This implementation invokes {@link AtmosClient#pathExists} * * @param container * container * @param key * file name */ @Override public boolean blobExists(String container, String key) { return sync.pathExists(container + "/" + key); } /** * This implementation invokes {@link AtmosClient#readFile} */ @Override public Blob getBlob(String container, String key, org.jclouds.blobstore.options.GetOptions options) { GetOptions httpOptions = blob2ObjectGetOptions.apply(options); return object2Blob.apply(sync.readFile(container + "/" + key, httpOptions)); } /** * This implementation invokes {@link AtmosClient#listDirectories} */ @Override public PageSet list() { return container2ResourceList.apply(sync.listDirectories()); } /** * This implementation invokes {@link AtmosClient#listDirectory} */ @Override public PageSet list(String container, org.jclouds.blobstore.options.ListContainerOptions options) { // TODO: recursive? if (!Strings.nullToEmpty(options.getDelimiter()).equals("/") && !Strings.isNullOrEmpty(options.getPrefix())) { throw new IllegalArgumentException("Atmos can only list via prefix if delimiter is / and the prefix matches an existing directory"); } container = AtmosUtils.adjustContainerIfDirOptionPresent(container, options); if (!Strings.isNullOrEmpty(options.getPrefix())) { // this only works when the prefix exactly matches a directory, the common usage container += "/" + options.getPrefix(); } ListOptions nativeOptions = container2ContainerListOptions.apply(options); // until includeMeta() option works for namespace interface PageSet list = container2ResourceList.apply(sync.listDirectory(container, nativeOptions)); return options.isDetailed() ? fetchBlobMetadataProvider.get().setContainerName(container).apply(list) : list; } /** * This implementation invokes {@link AtmosClient#createFile} *

* Since there is no etag support in atmos, we just return the path. */ @Override public String putBlob(final String container, final Blob blob) { return putBlob(container, blob, PutOptions.NONE); } /** * This implementation invokes {@link AtmosClient#createFile} *

* Since there is no etag support in atmos, we just return the path. */ @Override public String putBlob(String container, Blob blob, PutOptions options) { if (options.isMultipart()) { throw new UnsupportedOperationException("Atmos does not support multipart uploads"); } org.jclouds.atmos.options.PutOptions atmosOptions = new org.jclouds.atmos.options.PutOptions(); atmosOptions.publicNone(); try { // TODO: not needed if (isPublic.getUnchecked(container + "/")) atmosOptions.publicRead(); } catch (CacheLoader.InvalidCacheLoadException e) { // nulls not permitted } if (options.getBlobAccess() == BlobAccess.PUBLIC_READ) { atmosOptions.publicRead(); } return AtmosUtils.putBlob(sync, crypto, blob2Object, container, blob, atmosOptions); } /** * This implementation invokes {@link AtmosClient#deletePath} */ @Override public void removeBlob(String container, String key) { sync.deletePath(container + "/" + key); } @Override public BlobAccess getBlobAccess(String container, String key) { if (sync.isPublic(container + "/" + key)) { return BlobAccess.PUBLIC_READ; } else { return BlobAccess.PRIVATE; } } @Override public void setBlobAccess(String container, String key, BlobAccess access) { org.jclouds.atmos.options.PutOptions options = new org.jclouds.atmos.options.PutOptions(); if (access == BlobAccess.PUBLIC_READ) { options.publicRead(); } else { options.publicNone(); } sync.setGroupAcl(container + "/" + key, options); } @Override public boolean createContainerInLocation(Location location, String container, CreateContainerOptions options) { if (options.isPublicRead()) { return sync.createDirectory(container, publicRead()) != null; } return createContainerInLocation(location, container); } @Override public MultipartUpload initiateMultipartUpload(String container, BlobMetadata blobMetadata, PutOptions options) { throw new UnsupportedOperationException("Atmos does not support multipart uploads"); } @Override public void abortMultipartUpload(MultipartUpload mpu) { throw new UnsupportedOperationException("Atmos does not support multipart uploads"); } @Override public String completeMultipartUpload(MultipartUpload mpu, List parts) { throw new UnsupportedOperationException("Atmos does not support multipart uploads"); } @Override public MultipartPart uploadMultipartPart(MultipartUpload mpu, int partNumber, Payload payload) { throw new UnsupportedOperationException("Atmos does not support multipart uploads"); } @Override public List listMultipartUpload(MultipartUpload mpu) { throw new UnsupportedOperationException("Atmos does not support multipart uploads"); } @Override public List listMultipartUploads(String container) { throw new UnsupportedOperationException("Atmos does not support multipart uploads"); } @Override public long getMinimumMultipartPartSize() { throw new UnsupportedOperationException("Atmos does not support multipart uploads"); } @Override public long getMaximumMultipartPartSize() { throw new UnsupportedOperationException("Atmos does not support multipart uploads"); } @Override public int getMaximumNumberOfParts() { throw new UnsupportedOperationException("Atmos does not support multipart uploads"); } @Override public InputStream streamBlob(String container, String name) { throw new UnsupportedOperationException("Atmos does not support multipart uploads"); } @Override public String copyBlob(String fromContainer, String fromName, String toContainer, String toName, CopyOptions options) { if (options.ifMatch() != null) { throw new UnsupportedOperationException("Atmos does not support ifMatch"); } if (options.ifNoneMatch() != null) { throw new UnsupportedOperationException("Atmos does not support ifNoneMatch"); } return super.copyBlob(fromContainer, fromName, toContainer, toName, options); } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/blobstore/config/AtmosBlobStoreContextModule.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.blobstore.config; import java.util.concurrent.TimeUnit; import jakarta.inject.Singleton; import org.jclouds.atmos.AtmosClient; import org.jclouds.atmos.blobstore.AtmosBlobRequestSigner; import org.jclouds.atmos.blobstore.AtmosBlobStore; import org.jclouds.blobstore.BlobRequestSigner; import org.jclouds.blobstore.BlobStore; import org.jclouds.blobstore.attr.ConsistencyModel; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.inject.AbstractModule; import com.google.inject.Provides; import com.google.inject.Scopes; public class AtmosBlobStoreContextModule extends AbstractModule { @Override protected void configure() { bind(ConsistencyModel.class).toInstance(ConsistencyModel.EVENTUAL); bind(BlobStore.class).to(AtmosBlobStore.class).in(Scopes.SINGLETON); bind(BlobRequestSigner.class).to(AtmosBlobRequestSigner.class); } @Provides @Singleton protected final LoadingCache isPublic(final AtmosClient client) { return CacheBuilder.newBuilder().expireAfterWrite(30, TimeUnit.SECONDS).build(new CacheLoader() { @Override public String toString() { return "isPublic()"; } @Override public Boolean load(String arg0) throws Exception { return client.isPublic(arg0); } }); } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/blobstore/functions/BlobMetadataToObject.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.blobstore.functions; import java.util.Map.Entry; import jakarta.inject.Inject; import jakarta.inject.Singleton; import org.jclouds.atmos.domain.AtmosObject; import org.jclouds.atmos.domain.UserMetadata; import org.jclouds.blobstore.domain.BlobMetadata; import com.google.common.base.Function; @Singleton public class BlobMetadataToObject implements Function { private final AtmosObject.Factory factory; private final BlobToContentMetadata blob2ContentMd; private final BlobToSystemMetadata blob2SysMd; @Inject protected BlobMetadataToObject(AtmosObject.Factory factory, BlobToContentMetadata blob2ContentMd, BlobToSystemMetadata blob2SysMd) { this.factory = factory; this.blob2ContentMd = blob2ContentMd; this.blob2SysMd = blob2SysMd; } public AtmosObject apply(BlobMetadata from) { if (from == null) return null; UserMetadata userMd = new UserMetadata(); if (from.getUserMetadata() != null) { for (Entry entry : from.getUserMetadata().entrySet()) userMd.getMetadata().put(entry.getKey().toLowerCase(), entry.getValue()); } return factory.create(blob2ContentMd.apply(from), blob2SysMd.apply(from), userMd); } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/blobstore/functions/BlobStoreListOptionsToListOptions.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.blobstore.functions; import static com.google.common.base.Preconditions.checkNotNull; import jakarta.inject.Singleton; import org.jclouds.blobstore.options.ListContainerOptions; import com.google.common.base.Function; import com.google.common.base.Strings; @Singleton public class BlobStoreListOptionsToListOptions implements Function { @Override public org.jclouds.atmos.options.ListOptions apply(ListContainerOptions from) { checkNotNull(from, "set options to instance NONE instead of passing null"); org.jclouds.atmos.options.ListOptions httpOptions = new org.jclouds.atmos.options.ListOptions(); if (!Strings.isNullOrEmpty(from.getMarker())) { httpOptions.token(from.getMarker()); } if (from.getMaxResults() != null) { httpOptions.limit(from.getMaxResults()); } if (from.isDetailed()) { httpOptions.includeMeta(); } return httpOptions; } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/blobstore/functions/BlobToContentMetadata.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.blobstore.functions; import jakarta.inject.Singleton; import org.jclouds.atmos.domain.MutableContentMetadata; import org.jclouds.atmos.domain.internal.DelegatingMutableContentMetadata; import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.internal.MutableBlobMetadataImpl; import org.jclouds.http.HttpUtils; import com.google.common.base.Function; @Singleton public class BlobToContentMetadata implements Function { public MutableContentMetadata apply(BlobMetadata base) { MutableBlobMetadataImpl to = new MutableBlobMetadataImpl(); HttpUtils.copy(base.getContentMetadata(), to.getContentMetadata()); return new DelegatingMutableContentMetadata(base.getUri(), base.getName(), base.getUri() != null ? base.getUri() .getPath() : null, to.getContentMetadata()); } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/blobstore/functions/BlobToObject.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.blobstore.functions; import static com.google.common.base.Preconditions.checkNotNull; import jakarta.inject.Inject; import jakarta.inject.Singleton; import org.jclouds.atmos.domain.AtmosObject; import org.jclouds.blobstore.domain.Blob; import com.google.common.base.Function; @Singleton public class BlobToObject implements Function { private final BlobMetadataToObject blobMd2Object; @Inject BlobToObject(BlobMetadataToObject blobMd2Object) { this.blobMd2Object = blobMd2Object; } public AtmosObject apply(Blob from) { if (from == null) return null; AtmosObject object = blobMd2Object.apply(from.getMetadata()); object.setPayload(checkNotNull(from.getPayload(), "payload: " + from)); object.setAllHeaders(from.getAllHeaders()); return object; } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/blobstore/functions/BlobToSystemMetadata.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.blobstore.functions; import jakarta.inject.Singleton; import org.jclouds.atmos.domain.FileType; import org.jclouds.atmos.domain.SystemMetadata; import org.jclouds.blobstore.domain.BlobMetadata; import com.google.common.base.Function; @Singleton public class BlobToSystemMetadata implements Function { public SystemMetadata apply(BlobMetadata base) { return new SystemMetadata(base.getContentMetadata().getContentMD5(), null, base.getLastModified(), null, null, null, 1, null, base.getName(), null, (base.getContentMetadata().getContentLength() != null) ? base .getContentMetadata().getContentLength() : 0, FileType.REGULAR, "root"); } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/blobstore/functions/DirectoryEntryListToResourceMetadataList.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.blobstore.functions; import jakarta.inject.Inject; import jakarta.inject.Singleton; import org.jclouds.atmos.domain.BoundedSet; import org.jclouds.atmos.domain.DirectoryEntry; import org.jclouds.atmos.domain.FileType; import org.jclouds.blobstore.domain.PageSet; import org.jclouds.blobstore.domain.StorageMetadata; import org.jclouds.blobstore.domain.StorageType; import org.jclouds.blobstore.domain.internal.BlobMetadataImpl; import org.jclouds.blobstore.domain.internal.MutableBlobMetadataImpl; import org.jclouds.blobstore.domain.internal.PageSetImpl; import org.jclouds.blobstore.domain.internal.StorageMetadataImpl; import org.jclouds.domain.Location; import org.jclouds.io.payloads.BaseMutableContentMetadata; import com.google.common.base.Function; import com.google.common.base.Supplier; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; @Singleton public class DirectoryEntryListToResourceMetadataList implements Function, PageSet> { private Supplier defaultLocation; @Inject DirectoryEntryListToResourceMetadataList(Supplier defaultLocation) { this.defaultLocation = defaultLocation; } public PageSet apply(BoundedSet from) { return new PageSetImpl(Iterables.transform(from, new Function() { public StorageMetadata apply(DirectoryEntry from) { StorageType type = from.getType() == FileType.DIRECTORY ? StorageType.FOLDER : StorageType.BLOB; if (type == StorageType.FOLDER) return new StorageMetadataImpl(type, from.getObjectID(), from.getObjectName(), defaultLocation .get(), null, null, null, null, ImmutableMap.of()); else { BlobMetadataImpl metadata = new BlobMetadataImpl(from.getObjectID(), from.getObjectName(), defaultLocation.get(), null, from.getObjectID(), null, from.getModifiedTime(), ImmutableMap.of(), null, null, new BaseMutableContentMetadata()); MutableBlobMetadataImpl mutable = new MutableBlobMetadataImpl(metadata); mutable.setSize(from.getSize()); return mutable; } } }), from.getToken()); } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/blobstore/functions/ObjectToBlob.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.blobstore.functions; import static com.google.common.base.Preconditions.checkNotNull; import jakarta.inject.Inject; import jakarta.inject.Singleton; import org.jclouds.atmos.domain.AtmosObject; import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob.Factory; import org.jclouds.http.HttpUtils; import com.google.common.base.Function; @Singleton public class ObjectToBlob implements Function { private final Factory blobFactory; private final ObjectToBlobMetadata object2BlobMd; @Inject ObjectToBlob(Factory blobFactory, ObjectToBlobMetadata object2BlobMd) { this.blobFactory = blobFactory; this.object2BlobMd = object2BlobMd; } public Blob apply(AtmosObject from) { if (from == null) return null; Blob blob = blobFactory.create(object2BlobMd.apply(from)); blob.setPayload(checkNotNull(from.getPayload(), "payload: " + from)); HttpUtils.copy(from.getContentMetadata(), blob.getPayload().getContentMetadata()); blob.setAllHeaders(from.getAllHeaders()); return blob; } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/blobstore/functions/ObjectToBlobMetadata.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.blobstore.functions; import java.util.Map; import java.util.Set; import java.util.Map.Entry; import jakarta.inject.Inject; import jakarta.inject.Singleton; import org.jclouds.atmos.domain.AtmosObject; import org.jclouds.atmos.domain.FileType; import org.jclouds.atmos.filters.ShareUrl; import org.jclouds.atmos.functions.AtmosObjectName; import org.jclouds.blobstore.domain.MutableBlobMetadata; import org.jclouds.blobstore.domain.StorageType; import org.jclouds.blobstore.domain.Tier; import org.jclouds.blobstore.domain.internal.MutableBlobMetadataImpl; import org.jclouds.http.HttpUtils; import com.google.common.base.Function; import com.google.common.base.Splitter; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.common.collect.Maps; @Singleton public class ObjectToBlobMetadata implements Function { private final AtmosObjectName objectName; private final ShareUrl shareUrl; private static final Set systemMetadata = ImmutableSet.of("atime", "mtime", "ctime", "itime", "type", "uid", "gid", "objectid", "objname", "size", "nlink", "policyname"); @Inject protected ObjectToBlobMetadata(AtmosObjectName objectName, ShareUrl shareUrl) throws SecurityException, NoSuchMethodException { this.objectName = objectName; this.shareUrl = shareUrl; } public MutableBlobMetadata apply(AtmosObject from) { if (from == null) return null; MutableBlobMetadata to = new MutableBlobMetadataImpl(); to.setId(from.getSystemMetadata().getObjectID()); to.setLastModified(from.getSystemMetadata().getLastUserDataModification()); HttpUtils.copy(from.getContentMetadata(), to.getContentMetadata()); to.setName(objectName.apply(from)); to.setUri(from.getContentMetadata().getUri()); to.setContainer(Iterables.get(Splitter.on('/').split(from.getContentMetadata().getPath()), 0)); if (from.getAllHeaders().containsEntry("x-emc-groupacl", "other=READ")) to.setPublicUri(shareUrl.apply(from.getContentMetadata().getPath())); if (from.getSystemMetadata().getType() == FileType.DIRECTORY) { to.setType(StorageType.FOLDER); } else { to.setType(StorageType.BLOB); } Map lowerKeyMetadata = Maps.newHashMap(); for (Entry entry : from.getUserMetadata().getMetadata().entrySet()) { String key = entry.getKey().toLowerCase(); if (!systemMetadata.contains(key)) lowerKeyMetadata.put(key, entry.getValue()); } to.setUserMetadata(lowerKeyMetadata); to.setSize(from.getContentMetadata().getContentLength()); to.setTier(Tier.STANDARD); to.setETag(from.getSystemMetadata().getObjectID()); to.getContentMetadata().setContentMD5(from.getSystemMetadata().getContentMD5()); return to; } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/config/AtmosHttpApiModule.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.config; import java.util.Date; import java.util.concurrent.TimeUnit; import jakarta.inject.Named; import org.jclouds.Constants; import org.jclouds.atmos.AtmosClient; import org.jclouds.atmos.handlers.AtmosClientErrorRetryHandler; import org.jclouds.atmos.handlers.AtmosServerErrorRetryHandler; import org.jclouds.atmos.handlers.ParseAtmosErrorFromXmlContent; import org.jclouds.date.DateService; import org.jclouds.date.TimeStamp; import org.jclouds.http.HttpErrorHandler; import org.jclouds.http.HttpRetryHandler; import org.jclouds.http.annotation.ClientError; import org.jclouds.http.annotation.Redirection; import org.jclouds.http.annotation.ServerError; import org.jclouds.rest.ConfiguresHttpApi; import org.jclouds.rest.config.HttpApiModule; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; import com.google.inject.Provides; /** * Configures the EMC Atmos Online Storage authentication service connection, including logging and * http transport. */ @ConfiguresHttpApi public class AtmosHttpApiModule extends HttpApiModule { @Override protected void configure() { install(new AtmosParserModule()); install(new AtmosObjectModule()); super.configure(); } @Provides @TimeStamp protected final String guiceProvideTimeStamp(@TimeStamp Supplier cache) { return provideTimeStamp(cache); } protected String provideTimeStamp(@TimeStamp Supplier cache) { return cache.get(); } /** * borrowing concurrency code to ensure that caching takes place properly */ @Provides @TimeStamp final Supplier provideTimeStampCache(@Named(Constants.PROPERTY_SESSION_INTERVAL) long seconds, final DateService dateService) { return Suppliers.memoizeWithExpiration(new Supplier() { @Override public String get() { return dateService.rfc822DateFormat(); } }, seconds, TimeUnit.SECONDS); } @Provides @TimeStamp protected final Long provideShareableUrlTimeout() { return new Date().getTime() + TimeUnit.HOURS.toMillis(1); } @Override protected void bindErrorHandlers() { bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(ParseAtmosErrorFromXmlContent.class); bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(ParseAtmosErrorFromXmlContent.class); bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(ParseAtmosErrorFromXmlContent.class); } @Override protected void bindRetryHandlers() { bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(AtmosClientErrorRetryHandler.class); bind(HttpRetryHandler.class).annotatedWith(ServerError.class).to(AtmosServerErrorRetryHandler.class); } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/config/AtmosObjectModule.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.config; import org.jclouds.atmos.domain.AtmosObject; import org.jclouds.atmos.domain.MutableContentMetadata; import org.jclouds.blobstore.config.BlobStoreObjectModule; import com.google.inject.AbstractModule; import com.google.inject.Provides; /** * Configures the domain object mappings needed for all Atmos implementations */ public class AtmosObjectModule extends AbstractModule { /** * explicit factories are created here as it has been shown that Assisted Inject is extremely * inefficient. http://code.google.com/p/google-guice/issues/detail?id=435 */ @Override protected void configure() { // for converters install(new BlobStoreObjectModule()); } @Provides final AtmosObject provideAtmosObject(AtmosObject.Factory factory) { return factory.create((MutableContentMetadata) null); } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/config/AtmosParserModule.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.config; import org.jclouds.json.config.GsonModule.DateAdapter; import org.jclouds.json.config.GsonModule.Iso8601DateAdapter; import com.google.inject.AbstractModule; public class AtmosParserModule extends AbstractModule { @Override protected void configure() { bind(DateAdapter.class).to(Iso8601DateAdapter.class); } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/domain/AtmosError.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.domain; /** * When an Atmos Storage request is in error, the client receives an error response. * * Provides access to EMC Atmos Online Storage resources via their REST API. */ public class AtmosError { private final int code; private final String message; private String stringSigned; @Override public String toString() { return "AtmosError [code=" + code + ", message=" + message + (stringSigned != null ? (", stringSigned=" + stringSigned) : "") + "]"; } public AtmosError(int code, String message) { this.code = code; this.message = message; } public int getCode() { return code; } public String getMessage() { return message; } public void setStringSigned(String stringSigned) { this.stringSigned = stringSigned; } /** * @return what jclouds signed before sending the request. */ public String getStringSigned() { return stringSigned; } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/domain/AtmosObject.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.domain; import org.jclouds.atmos.domain.internal.AtmosObjectImpl.AtmosObjectFactory; import org.jclouds.io.PayloadEnclosing; import org.jclouds.javax.annotation.Nullable; import com.google.common.collect.Multimap; import com.google.inject.ImplementedBy; public interface AtmosObject extends PayloadEnclosing, Comparable { @ImplementedBy(AtmosObjectFactory.class) public interface Factory { AtmosObject create(@Nullable MutableContentMetadata contentMetadata); AtmosObject create(SystemMetadata systemMetadata, UserMetadata userMetadata); AtmosObject create(MutableContentMetadata contentMetadata, SystemMetadata systemMetadata, UserMetadata userMetadata); } MutableContentMetadata getContentMetadata(); /** * @return System and User metadata relevant to this object. */ SystemMetadata getSystemMetadata(); UserMetadata getUserMetadata(); Multimap getAllHeaders(); void setAllHeaders(Multimap allHeaders); } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/domain/BoundedSet.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.domain; import java.util.Set; import org.jclouds.atmos.domain.internal.BoundedLinkedHashSet; import org.jclouds.javax.annotation.Nullable; import com.google.inject.ImplementedBy; @ImplementedBy(BoundedLinkedHashSet.class) public interface BoundedSet extends Set { @Nullable String getToken(); } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/domain/DirectoryEntry.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.domain; import java.util.Date; import org.jclouds.javax.annotation.Nullable; import com.google.common.base.Objects; /** * Metadata of a Atmos Online object */ public class DirectoryEntry implements Comparable { private final String objectid; private final FileType type; private final String objname; private final long size; @Nullable private final Date modifiedTime; @Deprecated public DirectoryEntry(String objectid, FileType type, String objname, long size) { this(objectid, type, objname, size, null); } public DirectoryEntry(String objectid, FileType type, String objname, long size, Date modifiedTime) { this.objectid = objectid; this.objname = objname; this.type = type; this.size = size; this.modifiedTime = modifiedTime != null ? (Date) modifiedTime.clone() : null; } public String getObjectID() { return objectid; } public String getObjectName() { return objname; } public FileType getType() { return type; } public long getSize() { return size; } public Date getModifiedTime() { return modifiedTime != null ? (Date) modifiedTime.clone() : null; } public int compareTo(DirectoryEntry o) { if (getObjectName() == null) return -1; return (this == o) ? 0 : getObjectName().compareTo(o.getObjectName()); } @Override public int hashCode() { return Objects.hashCode(objectid, objname, type, size); } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; DirectoryEntry other = (DirectoryEntry) obj; return Objects.equal(objectid, other.objectid) && Objects.equal(objname, other.objname) && Objects.equal(type, other.type) && Objects.equal(size, other.size); } @Override public String toString() { return "DirectoryEntry [type=" + type + ", objectid=" + objectid + ", objname=" + objname + ", size=" + size + "]"; } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/domain/FileType.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.domain; public enum FileType { DIRECTORY, REGULAR, UNRECOGNIZED; public String value() { return name().toLowerCase(); } public static FileType fromValue(String v) { try { return valueOf(v.toUpperCase()); } catch (IllegalArgumentException e) { return UNRECOGNIZED; } } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/domain/MutableContentMetadata.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.domain; import java.net.URI; import org.jclouds.atmos.domain.internal.DelegatingMutableContentMetadata; import com.google.inject.ImplementedBy; /** * metadata of the object */ @ImplementedBy(DelegatingMutableContentMetadata.class) public interface MutableContentMetadata extends org.jclouds.io.MutableContentMetadata { String getName(); void setName(String name); URI getUri(); void setUri(URI uri); String getPath(); void setPath(String path); } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/domain/SystemMetadata.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.domain; import java.util.Date; import org.jclouds.javax.annotation.Nullable; /** * Metadata of a Atmos Online object */ public class SystemMetadata extends DirectoryEntry { private final Date atime; private final Date ctime; private final String gid; private final Date itime; private final Date mtime; private final int nlink; private final String policyname; private final long size; private final String uid; private final byte[] contentmd5; public SystemMetadata(@Nullable byte [] contentmd5, Date atime, Date ctime, String gid, Date itime, Date mtime, int nlink, String objectid, String objname, String policyname, long size, FileType type, String uid) { super(objectid, type, objname, size); this.contentmd5 = contentmd5; this.atime = atime; this.ctime = ctime; this.gid = gid; this.itime = itime; this.mtime = mtime; this.nlink = nlink; this.policyname = policyname; this.size = size; this.uid = uid; } public String getGroupID() { return gid; } public int getHardLinkCount() { return nlink; } public Date getInceptionTime() { return itime; } public Date getLastAccessTime() { return atime; } public Date getLastMetadataModification() { return mtime; } public Date getLastUserDataModification() { return ctime; } public String getPolicyName() { return policyname; } public long getSize() { return size; } public String getUserID() { return uid; } public byte[] getContentMD5() { return contentmd5; } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + ((atime == null) ? 0 : atime.hashCode()); result = prime * result + ((ctime == null) ? 0 : ctime.hashCode()); result = prime * result + ((gid == null) ? 0 : gid.hashCode()); result = prime * result + ((itime == null) ? 0 : itime.hashCode()); result = prime * result + ((mtime == null) ? 0 : mtime.hashCode()); result = prime * result + nlink; result = prime * result + ((policyname == null) ? 0 : policyname.hashCode()); result = prime * result + (int) (size ^ (size >>> 32)); result = prime * result + ((uid == null) ? 0 : uid.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (getClass() != obj.getClass()) return false; SystemMetadata other = (SystemMetadata) obj; if (atime == null) { if (other.atime != null) return false; } else if (!atime.equals(other.atime)) return false; if (ctime == null) { if (other.ctime != null) return false; } else if (!ctime.equals(other.ctime)) return false; if (gid == null) { if (other.gid != null) return false; } else if (!gid.equals(other.gid)) return false; if (itime == null) { if (other.itime != null) return false; } else if (!itime.equals(other.itime)) return false; if (mtime == null) { if (other.mtime != null) return false; } else if (!mtime.equals(other.mtime)) return false; if (nlink != other.nlink) return false; if (policyname == null) { if (other.policyname != null) return false; } else if (!policyname.equals(other.policyname)) return false; if (size != other.size) return false; if (uid == null) { if (other.uid != null) return false; } else if (!uid.equals(other.uid)) return false; return true; } @Override public String toString() { return "[type=" + getType() + ", id=" + getObjectID() + ", name=" + getObjectName() + "]"; } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/domain/UploadInfo.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.domain; import java.net.URI; public class UploadInfo { private final String token; private final URI host; public UploadInfo(String token, URI host) { this.token = token; this.host = host; } public String getToken() { return token; } public URI getHost() { return host; } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/domain/UserMetadata.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.domain; import static com.google.common.base.Preconditions.checkNotNull; import java.util.Map; import java.util.Set; import com.google.common.collect.Maps; import com.google.common.collect.Sets; /** * User metadata */ public class UserMetadata { private final Map metadata; private final Map listableMetadata; private final Set tags; private final Set listableTags; public UserMetadata(Map metadata, Map listableMetadata, Iterable tags, Iterable listableTags) { this.metadata = Maps.newLinkedHashMap(checkNotNull(metadata, "metadata")); this.listableMetadata = Maps.newLinkedHashMap(checkNotNull(listableMetadata, "listableMetadata")); this.tags = Sets.newLinkedHashSet(checkNotNull(tags, "tags")); this.listableTags = Sets.newLinkedHashSet(checkNotNull(listableTags, "listableTags")); } public UserMetadata() { this.metadata = Maps.newLinkedHashMap(); this.listableMetadata = Maps.newLinkedHashMap(); this.tags = Sets.newLinkedHashSet(); this.listableTags = Sets.newLinkedHashSet(); } public Map getMetadata() { return metadata; } public Map getListableMetadata() { return listableMetadata; } public Set getTags() { return tags; } public Set getListableTags() { return listableTags; } @Override public String toString() { return "[metadata=" + metadata + ", listableMetadata=" + listableMetadata + ", tags=" + tags + ", listableTags=" + listableTags + "]"; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((listableMetadata == null) ? 0 : listableMetadata.hashCode()); result = prime * result + ((listableTags == null) ? 0 : listableTags.hashCode()); result = prime * result + ((metadata == null) ? 0 : metadata.hashCode()); result = prime * result + ((tags == null) ? 0 : tags.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; UserMetadata other = (UserMetadata) obj; if (listableMetadata == null) { if (other.listableMetadata != null) return false; } else if (!listableMetadata.equals(other.listableMetadata)) return false; if (listableTags == null) { if (other.listableTags != null) return false; } else if (!listableTags.equals(other.listableTags)) return false; if (metadata == null) { if (other.metadata != null) return false; } else if (!metadata.equals(other.metadata)) return false; if (tags == null) { if (other.tags != null) return false; } else if (!tags.equals(other.tags)) return false; return true; } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/domain/internal/AtmosObjectImpl.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.domain.internal; import static com.google.common.base.Preconditions.checkNotNull; import jakarta.inject.Inject; import jakarta.inject.Provider; import jakarta.inject.Singleton; import org.jclouds.atmos.domain.AtmosObject; import org.jclouds.atmos.domain.MutableContentMetadata; import org.jclouds.atmos.domain.SystemMetadata; import org.jclouds.atmos.domain.UserMetadata; import org.jclouds.http.internal.PayloadEnclosingImpl; import org.jclouds.io.Payload; import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.Multimap; /** * Default Implementation of {@link AtmosObject}. */ public class AtmosObjectImpl extends PayloadEnclosingImpl implements AtmosObject, Comparable { @Singleton public static class AtmosObjectFactory implements AtmosObject.Factory { @Inject Provider metadataProvider; public AtmosObject create(MutableContentMetadata contentMetadata) { return new AtmosObjectImpl(contentMetadata != null ? contentMetadata : metadataProvider.get()); } public AtmosObject create(SystemMetadata systemMetadata, UserMetadata userMetadata) { return new AtmosObjectImpl(metadataProvider.get(), systemMetadata, userMetadata); } public AtmosObject create(MutableContentMetadata contentMetadata, SystemMetadata systemMetadata, UserMetadata userMetadata) { return new AtmosObjectImpl(contentMetadata, systemMetadata, userMetadata); } } private final UserMetadata userMetadata; private final SystemMetadata systemMetadata; public SystemMetadata getSystemMetadata() { return systemMetadata; } public UserMetadata getUserMetadata() { return userMetadata; } private MutableContentMetadata contentMetadata; private Multimap allHeaders = LinkedHashMultimap.create(); public AtmosObjectImpl(MutableContentMetadata contentMetadata, SystemMetadata systemMetadata, UserMetadata userMetadata) { this.contentMetadata = contentMetadata; this.systemMetadata = systemMetadata; this.userMetadata = userMetadata; } @Inject public AtmosObjectImpl(MutableContentMetadata contentMetadata) { this(contentMetadata, null, new UserMetadata()); } /** * {@inheritDoc} */ @Override public MutableContentMetadata getContentMetadata() { return contentMetadata; } /** * {@inheritDoc} */ @Override public Multimap getAllHeaders() { return allHeaders; } /** * {@inheritDoc} */ @Override public void setAllHeaders(Multimap allHeaders) { this.allHeaders = checkNotNull(allHeaders, "allHeaders"); } /** * {@inheritDoc} */ @Override public int compareTo(AtmosObject o) { if (getContentMetadata().getName() == null) return -1; return (this == o) ? 0 : getContentMetadata().getName().compareTo(o.getContentMetadata().getName()); } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + ((contentMetadata == null) ? 0 : contentMetadata.hashCode()); result = prime * result + ((systemMetadata == null) ? 0 : systemMetadata.hashCode()); result = prime * result + ((userMetadata == null) ? 0 : userMetadata.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (getClass() != obj.getClass()) return false; AtmosObjectImpl other = (AtmosObjectImpl) obj; if (contentMetadata == null) { if (other.contentMetadata != null) return false; } else if (!contentMetadata.equals(other.contentMetadata)) return false; if (systemMetadata == null) { if (other.systemMetadata != null) return false; } else if (!systemMetadata.equals(other.systemMetadata)) return false; if (userMetadata == null) { if (other.userMetadata != null) return false; } else if (!userMetadata.equals(other.userMetadata)) return false; return true; } @Override public String toString() { return "[contentMetadata=" + contentMetadata + "]"; } @Override public void setPayload(Payload data) { this.payload = data; this.contentMetadata = new DelegatingMutableContentMetadata(contentMetadata.getUri(), contentMetadata.getName(), contentMetadata.getPath(), payload.getContentMetadata()); } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/domain/internal/BoundedLinkedHashSet.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.domain.internal; import static com.google.common.base.Preconditions.checkNotNull; import java.util.LinkedHashSet; import org.jclouds.atmos.domain.BoundedSet; import org.jclouds.javax.annotation.Nullable; import com.google.common.collect.Iterables; public class BoundedLinkedHashSet extends LinkedHashSet implements BoundedSet { protected final String token; public BoundedLinkedHashSet(Iterable contents, @Nullable String token) { Iterables.addAll(this, checkNotNull(contents, "contents")); this.token = token; } @Nullable public String getToken() { return token; } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + ((token == null) ? 0 : token.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (getClass() != obj.getClass()) return false; BoundedLinkedHashSet other = (BoundedLinkedHashSet) obj; if (token == null) { if (other.token != null) return false; } else if (!token.equals(other.token)) return false; return true; } @Override public String toString() { return "[token=" + token + ", contents=" + super.toString() + "]"; } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/domain/internal/DelegatingMutableContentMetadata.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.domain.internal; import java.net.URI; import java.util.Date; import org.jclouds.atmos.domain.MutableContentMetadata; import org.jclouds.io.ContentMetadataBuilder; import org.jclouds.io.payloads.BaseMutableContentMetadata; import com.google.common.hash.HashCode; public class DelegatingMutableContentMetadata implements MutableContentMetadata { private URI uri; private String name; private String path; private final org.jclouds.io.MutableContentMetadata delegate; public DelegatingMutableContentMetadata() { this(null, null, null, new BaseMutableContentMetadata()); } public DelegatingMutableContentMetadata(URI uri, String name, String path, org.jclouds.io.MutableContentMetadata delegate) { this.uri = uri; this.name = name; this.delegate = delegate; this.path = path; } @Override public Long getContentLength() { return delegate.getContentLength(); } /** @deprecated use {@link #getContentMD5AsHashCode()} instead. */ @Deprecated @Override public byte[] getContentMD5() { return delegate.getContentMD5(); } @Override public HashCode getContentMD5AsHashCode() { return delegate.getContentMD5AsHashCode(); } @Override public String getContentType() { return delegate.getContentType(); } @Override public String getName() { return name; } @Override public void setContentLength(Long contentLength) { delegate.setContentLength(contentLength); } /** @deprecated use {@link #setContentMD5(HashCode)} instead. */ @Deprecated @Override public void setContentMD5(byte[] contentMD5) { delegate.setContentMD5(contentMD5); } @Override public void setContentMD5(HashCode contentMD5) { delegate.setContentMD5(contentMD5); } @Override public void setContentType(String contentType) { delegate.setContentType(contentType); } @Override public void setName(String name) { this.name = name; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; DelegatingMutableContentMetadata other = (DelegatingMutableContentMetadata) obj; if (uri == null) { if (other.uri != null) return false; } else if (!uri.equals(other.uri)) return false; return true; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((uri == null) ? 0 : uri.hashCode()); return result; } @Override public String toString() { return "[uri=" + uri + ", name=" + name + ", path=" + path + ", delegate=" + delegate + "]"; } public org.jclouds.io.MutableContentMetadata getDelegate() { return delegate; } @Override public void setCacheControl(String cacheControl) { delegate.setCacheControl(cacheControl); } @Override public void setContentDisposition(String contentDisposition) { delegate.setContentDisposition(contentDisposition); } @Override public void setContentEncoding(String contentEncoding) { delegate.setContentEncoding(contentEncoding); } @Override public void setContentLanguage(String contentLanguage) { delegate.setContentLanguage(contentLanguage); } @Override public String getCacheControl() { return delegate.getCacheControl(); } @Override public String getContentDisposition() { return delegate.getContentDisposition(); } @Override public String getContentEncoding() { return delegate.getContentEncoding(); } @Override public String getContentLanguage() { return delegate.getContentLanguage(); } @Override public void setExpires(Date expires) { delegate.setExpires(expires); } @Override public Date getExpires() { return delegate.getExpires(); } @Override public ContentMetadataBuilder toBuilder() { return delegate.toBuilder(); } @Override public URI getUri() { return uri; } @Override public void setUri(URI uri) { this.uri = uri; } @Override public String getPath() { return path; } @Override public void setPath(String path) { this.path = path; } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/fallbacks/EndpointIfAlreadyExists.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.fallbacks; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Throwables.propagate; import java.net.URI; import org.jclouds.Fallback; import org.jclouds.blobstore.KeyAlreadyExistsException; import org.jclouds.http.HttpRequest; import org.jclouds.javax.annotation.Nullable; import org.jclouds.rest.InvocationContext; import com.google.common.annotations.VisibleForTesting; public class EndpointIfAlreadyExists implements Fallback, InvocationContext { private URI endpoint; @Override public URI createOrPropagate(Throwable t) throws Exception { if (checkNotNull(t, "throwable") instanceof KeyAlreadyExistsException) { return endpoint; } throw propagate(t); } @Override public EndpointIfAlreadyExists setContext(HttpRequest request) { return setEndpoint(request == null ? null : request.getEndpoint()); } @VisibleForTesting EndpointIfAlreadyExists setEndpoint(@Nullable URI endpoint) { this.endpoint = endpoint; return this; } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/fallbacks/TrueOn404FalseOnPathNotEmpty.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.fallbacks; import static com.google.common.base.Throwables.propagate; import static org.jclouds.util.Throwables2.getFirstThrowableOfType; import org.jclouds.Fallback; import org.jclouds.atmos.AtmosResponseException; import org.jclouds.atmos.reference.AtmosErrorCode; import org.jclouds.http.HttpUtils; public final class TrueOn404FalseOnPathNotEmpty implements Fallback { @Override public Boolean createOrPropagate(Throwable t) throws Exception { if (HttpUtils.contains404(t)) { return true; } AtmosResponseException exception = getFirstThrowableOfType(t, AtmosResponseException.class); if (exception != null && exception.getError().getCode() == AtmosErrorCode.DIRECTORY_NOT_EMPTY.getCode()) { return false; } throw propagate(t); } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/filters/ShareUrl.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.filters; import static com.google.common.base.Throwables.propagate; import static com.google.common.io.BaseEncoding.base64; import static com.google.common.io.ByteStreams.readBytes; import static org.jclouds.Constants.LOGGER_SIGNATURE; import static org.jclouds.crypto.Macs.asByteProcessor; import static org.jclouds.http.Uris.uriBuilder; import static org.jclouds.util.Strings2.toInputStream; import java.io.IOException; import java.net.URI; import java.security.InvalidKeyException; import jakarta.annotation.Resource; import jakarta.inject.Inject; import jakarta.inject.Named; import jakarta.inject.Singleton; import org.jclouds.crypto.Crypto; import org.jclouds.date.TimeStamp; import org.jclouds.domain.Credentials; import org.jclouds.http.HttpException; import org.jclouds.location.Provider; import org.jclouds.logging.Logger; import com.google.common.base.Function; import com.google.common.base.Supplier; import com.google.common.collect.ImmutableMap; import com.google.common.io.ByteProcessor; /** * Signs the EMC Atmos Online Storage request. * * @see */ @Singleton public class ShareUrl implements Function { private final Supplier creds; private final Supplier provider; private final jakarta.inject.Provider timeStampProvider; private final Crypto crypto; @Resource Logger logger = Logger.NULL; @Resource @Named(LOGGER_SIGNATURE) Logger signatureLog = Logger.NULL; @Inject public ShareUrl(@Provider Supplier creds, @Provider Supplier provider, @TimeStamp jakarta.inject.Provider timeStampProvider, Crypto crypto) { this.creds = creds; this.provider = provider; this.timeStampProvider = timeStampProvider; this.crypto = crypto; } @Override public URI apply(String path) throws HttpException { String requestedResource = new StringBuilder().append("/rest/namespace/").append(path).toString(); String expires = timeStampProvider.get().toString(); String signature = signString(createStringToSign(requestedResource, expires)); return uriBuilder(provider.get()) .replaceQuery(ImmutableMap.of("uid", creds.get().identity, "expires", expires, "signature", signature)) .appendPath(requestedResource).build(); } public String createStringToSign(String requestedResource, String expires) { StringBuilder toSign = new StringBuilder(); toSign.append("GET\n"); toSign.append(requestedResource.toLowerCase()).append("\n"); toSign.append(creds.get().identity).append("\n"); toSign.append(expires); return toSign.toString(); } public String signString(String toSign) { try { ByteProcessor hmacSHA1 = asByteProcessor(crypto.hmacSHA1(base64().decode(creds.get().credential))); return base64().encode(readBytes(toInputStream(toSign), hmacSHA1)); } catch (InvalidKeyException e) { throw propagate(e); } catch (IOException e) { throw propagate(e); } } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/filters/SignRequest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.filters; import static com.google.common.io.BaseEncoding.base64; import static com.google.common.io.ByteStreams.readBytes; import static org.jclouds.Constants.LOGGER_SIGNATURE; import static org.jclouds.crypto.Macs.asByteProcessor; import static org.jclouds.util.Patterns.NEWLINE_PATTERN; import static org.jclouds.util.Strings2.toInputStream; import java.util.Set; import jakarta.annotation.Resource; import jakarta.inject.Inject; import jakarta.inject.Named; import jakarta.inject.Provider; import jakarta.inject.Singleton; import org.jclouds.atmos.reference.AtmosHeaders; import org.jclouds.crypto.Crypto; import org.jclouds.date.TimeStamp; import org.jclouds.domain.Credentials; import org.jclouds.http.HttpException; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequestFilter; import org.jclouds.http.HttpUtils; import org.jclouds.http.internal.SignatureWire; import org.jclouds.logging.Logger; import org.jclouds.util.Strings2; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Strings; import com.google.common.base.Supplier; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap.Builder; import com.google.common.collect.Multimaps; import com.google.common.collect.Sets; import com.google.common.io.ByteProcessor; import com.google.common.net.HttpHeaders; /** * Signs the EMC Atmos Online Storage request. * * @see */ @Singleton public class SignRequest implements HttpRequestFilter { private final SignatureWire signatureWire; private final Supplier creds; private final Provider timeStampProvider; private final Crypto crypto; private final HttpUtils utils; @Resource Logger logger = Logger.NULL; @Resource @Named(LOGGER_SIGNATURE) Logger signatureLog = Logger.NULL; @Inject public SignRequest(SignatureWire signatureWire, @org.jclouds.location.Provider Supplier creds, @TimeStamp Provider timeStampProvider, Crypto crypto, HttpUtils utils) { this.signatureWire = signatureWire; this.creds = creds; this.timeStampProvider = timeStampProvider; this.crypto = crypto; this.utils = utils; } @Override public HttpRequest filter(HttpRequest request) throws HttpException { Builder builder = ImmutableMap.builder(); builder.put(AtmosHeaders.UID, creds.get().identity); String date = timeStampProvider.get(); builder.put(HttpHeaders.DATE, date); if (request.getFirstHeaderOrNull(AtmosHeaders.DATE) != null) builder.put(AtmosHeaders.DATE, date); request = request.toBuilder().replaceHeaders(Multimaps.forMap(builder.build())).build(); String signature = calculateSignature(createStringToSign(request)); request = request.toBuilder().replaceHeader(AtmosHeaders.SIGNATURE, signature).build(); utils.logRequest(signatureLog, request, "<<"); return request; } public String createStringToSign(HttpRequest request) { utils.logRequest(signatureLog, request, ">>"); StringBuilder buffer = new StringBuilder(); // re-sign the request appendMethod(request, buffer); appendPayloadMetadata(request, buffer); appendHttpHeaders(request, buffer); appendCanonicalizedResource(request, buffer); appendCanonicalizedHeaders(request, buffer); if (signatureWire.enabled()) signatureWire.output(buffer.toString()); return buffer.toString(); } public String calculateSignature(String toSign) { String signature = signString(toSign); if (signatureWire.enabled()) signatureWire.input(Strings2.toInputStream(signature)); return signature; } public String signString(String toSign) { try { ByteProcessor hmacSHA1 = asByteProcessor(crypto.hmacSHA1(base64().decode(creds.get().credential))); return base64().encode(readBytes(toInputStream(toSign), hmacSHA1)); } catch (Exception e) { throw new HttpException("error signing request", e); } } private void appendMethod(HttpRequest request, StringBuilder toSign) { toSign.append(request.getMethod()).append("\n"); } private void appendCanonicalizedHeaders(HttpRequest request, StringBuilder toSign) { // TreeSet == Sort the headers alphabetically. Set headers = Sets.newTreeSet(request.getHeaders().keySet()); for (String header : headers) { if (header.startsWith("x-emc-") && !header.equals(AtmosHeaders.SIGNATURE)) { // Convert all header names to lowercase. toSign.append(header.toLowerCase()).append(":"); // For headers with values that span multiple lines, convert them into one line by // replacing any // newline characters and extra embedded white spaces in the value. for (String value : request.getHeaders().get(header)) { value = value.replace(" ", " "); value = NEWLINE_PATTERN.matcher(value).replaceAll(""); toSign.append(value).append(' '); } toSign.deleteCharAt(toSign.lastIndexOf(" ")); // Concatenate all headers together, using newlines (\n) separating each header from the // next one. toSign.append("\n"); } } // There should be no terminating newline character at the end of the last header. if (toSign.charAt(toSign.length() - 1) == '\n') toSign.deleteCharAt(toSign.length() - 1); } private void appendPayloadMetadata(HttpRequest request, StringBuilder buffer) { buffer.append( Strings.nullToEmpty(request.getPayload() == null ? null : request.getPayload().getContentMetadata() .getContentType())).append("\n"); } @VisibleForTesting void appendHttpHeaders(HttpRequest request, StringBuilder toSign) { // Only the value is used, not the header // name. If a request does not include the header, this is an empty string. toSign.append(HttpUtils.nullToEmpty(request.getHeaders().get("Range")).toLowerCase()).append("\n"); // Standard HTTP header, in UTC format. Only the date value is used, not the header name. toSign.append(request.getFirstHeaderOrNull(HttpHeaders.DATE)).append("\n"); } @VisibleForTesting void appendCanonicalizedResource(HttpRequest request, StringBuilder toSign) { // Path portion of the HTTP request URI, in lowercase. toSign.append(request.getEndpoint().getRawPath().toLowerCase()); String query = request.getEndpoint().getRawQuery(); if (query != null) { toSign.append("?").append(query); } toSign.append("\n"); } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/functions/AtmosObjectName.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.functions; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import jakarta.inject.Singleton; import org.jclouds.atmos.domain.AtmosObject; import com.google.common.base.Function; @Singleton public class AtmosObjectName implements Function { @Override public String apply(Object input) { checkArgument(checkNotNull(input, "input") instanceof AtmosObject, "this function is only valid for AtmosObjects!"); AtmosObject object = AtmosObject.class.cast(input); return checkNotNull(object.getContentMetadata().getName() != null ? object.getContentMetadata().getName() : object.getSystemMetadata().getObjectName(), "objectName"); } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/functions/ParseDirectoryListFromContentAndHeaders.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.functions; import static com.google.common.base.Preconditions.checkNotNull; import jakarta.inject.Inject; import jakarta.inject.Provider; import jakarta.inject.Singleton; import org.jclouds.atmos.domain.BoundedSet; import org.jclouds.atmos.domain.DirectoryEntry; import org.jclouds.atmos.domain.internal.BoundedLinkedHashSet; import org.jclouds.atmos.reference.AtmosHeaders; import org.jclouds.atmos.xml.ListDirectoryResponseHandler; import org.jclouds.http.HttpResponse; import org.jclouds.http.functions.ParseSax; import org.jclouds.http.functions.ParseSax.Factory; import com.google.common.base.Function; /** * This parses {@link BoundedSet} from HTTP headers and xml content. */ @Singleton public class ParseDirectoryListFromContentAndHeaders implements Function> { private final ParseSax.Factory factory; private final Provider listHandlerProvider; @Inject ParseDirectoryListFromContentAndHeaders(Factory factory, Provider listHandlerProvider) { this.factory = checkNotNull(factory, "factory"); this.listHandlerProvider = checkNotNull(listHandlerProvider, "listHandlerProvider"); } /** * parses the http response headers to create a new {@link BoundedSet} object. */ public BoundedSet apply(HttpResponse from) { checkNotNull(from, "http response"); String token = from.getFirstHeaderOrNull(AtmosHeaders.TOKEN); return new BoundedLinkedHashSet(factory.create(listHandlerProvider.get()).parse( from.getPayload().getInput()), token); } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/functions/ParseObjectFromHeadersAndHttpContent.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.functions; import static com.google.common.base.Preconditions.checkNotNull; import static org.jclouds.http.HttpUtils.attemptToParseSizeAndRangeFromHeaders; import java.net.URI; import jakarta.inject.Inject; import org.jclouds.atmos.domain.AtmosObject; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; import org.jclouds.rest.InvocationContext; import org.jclouds.rest.internal.GeneratedHttpRequest; import com.google.common.base.Function; /** * Parses response headers and creates a new AtmosObject from them and the HTTP content. * * @see ParseMetadataFromHeaders */ public class ParseObjectFromHeadersAndHttpContent implements Function, InvocationContext { private final ParseSystemMetadataFromHeaders systemMetadataParser; private final ParseUserMetadataFromHeaders userMetadataParser; private final AtmosObject.Factory objectProvider; private URI uri; private String path; @Inject public ParseObjectFromHeadersAndHttpContent(ParseSystemMetadataFromHeaders systemMetadataParser, ParseUserMetadataFromHeaders userMetadataParser, AtmosObject.Factory objectProvider) { this.systemMetadataParser = checkNotNull(systemMetadataParser, "systemMetadataParser"); this.userMetadataParser = checkNotNull(userMetadataParser, "userMetadataParser"); this.objectProvider = checkNotNull(objectProvider, "objectProvider"); } /** * First, calls {@link ParseSystemAndUserMetadataFromHeaders}. * * Then, sets the object size based on the Content-Length header and adds the content to the * {@link AtmosObject} result. * * @throws org.jclouds.http.HttpException */ public AtmosObject apply(HttpResponse from) { checkNotNull(from, "http response"); AtmosObject object = objectProvider.create(systemMetadataParser.apply(from), userMetadataParser.apply(from)); object.getContentMetadata().setName(object.getSystemMetadata().getObjectName()); object.getContentMetadata().setPath(path); object.getContentMetadata().setUri(uri); object.getAllHeaders().putAll(from.getHeaders()); object.setPayload(from.getPayload()); object.getContentMetadata().setContentLength(attemptToParseSizeAndRangeFromHeaders(from)); object.getContentMetadata().setContentMD5(object.getSystemMetadata().getContentMD5()); return object; } @Override public ParseObjectFromHeadersAndHttpContent setContext(HttpRequest request) { this.uri = request.getEndpoint(); return setPath(GeneratedHttpRequest.class.cast(request).getInvocation().getArgs().get(0).toString()); } private ParseObjectFromHeadersAndHttpContent setPath(String path) { this.path = path; return this; } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/functions/ParseSystemMetadataFromHeaders.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.functions; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.io.BaseEncoding.base16; import java.util.Map; import jakarta.inject.Inject; import jakarta.inject.Singleton; import org.jclouds.atmos.domain.FileType; import org.jclouds.atmos.domain.SystemMetadata; import org.jclouds.atmos.reference.AtmosHeaders; import org.jclouds.date.DateService; import org.jclouds.http.HttpResponse; import com.google.common.base.Function; import com.google.common.base.Splitter; @Singleton public class ParseSystemMetadataFromHeaders implements Function { private final DateService dateService; @Inject public ParseSystemMetadataFromHeaders(DateService dateService) { this.dateService = checkNotNull(dateService, "dateService"); } public SystemMetadata apply(HttpResponse from) { checkNotNull(from, "http response"); String meta = checkNotNull(from.getFirstHeaderOrNull(AtmosHeaders.META), AtmosHeaders.META); Map metaMap = Splitter.on(", ").withKeyValueSeparator('=').split(meta); assert metaMap.size() >= 12 : String.format("Should be 12 entries in %s", metaMap); byte[] md5 = null; String wschecksum = from.getFirstHeaderOrNull(AtmosHeaders.CHECKSUM); if (wschecksum != null) { String[] parts = wschecksum.split("/"); if (parts[0].equalsIgnoreCase("MD5") && parts.length == 3) { md5 = base16().lowerCase().decode(parts[2]); } } return new SystemMetadata(md5, dateService.iso8601SecondsDateParse(checkNotNull(metaMap.get("atime"), "atime")), dateService.iso8601SecondsDateParse(checkNotNull(metaMap.get("ctime"), "ctime")), checkNotNull( metaMap.get("gid"), "gid"), dateService.iso8601SecondsDateParse(checkNotNull(metaMap.get("itime"), "itime")), dateService.iso8601SecondsDateParse(checkNotNull(metaMap.get("mtime"), "mtime")), Integer.parseInt(checkNotNull(metaMap.get("nlink"), "nlink")), checkNotNull(metaMap.get("objectid"), "objectid"), checkNotNull(metaMap.get("objname"), "objname"), checkNotNull(metaMap.get("policyname"), "policyname"), Long.parseLong(checkNotNull(metaMap.get("size"), "size")), FileType.fromValue(checkNotNull(metaMap.get("type"), "type")), checkNotNull(metaMap.get("uid"), "uid")); } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/functions/ParseUserMetadataFromHeaders.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.functions; import static com.google.common.base.Preconditions.checkNotNull; import java.util.Map; import java.util.Set; import jakarta.inject.Singleton; import org.jclouds.atmos.domain.UserMetadata; import org.jclouds.atmos.reference.AtmosHeaders; import org.jclouds.http.HttpResponse; import com.google.common.base.Function; import com.google.common.base.Predicates; import com.google.common.base.Splitter; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; @Singleton public class ParseUserMetadataFromHeaders implements Function { private static final Set SYS_KEYS = ImmutableSet.of( "atime", "ctime", "gid", "itime", "mtime", "nlink", "parent", "policyname", "size", "uid", "content-md5", "objectid", "objname", "type"); public UserMetadata apply(HttpResponse from) { checkNotNull(from, "http response"); Map meta = Maps.filterKeys( getMetaMap(checkNotNull(from.getFirstHeaderOrNull(AtmosHeaders.META), AtmosHeaders.META)), Predicates.not(Predicates.in(SYS_KEYS))); Map listableMeta = (from.getFirstHeaderOrNull(AtmosHeaders.LISTABLE_META) != null) ? getMetaMap(from .getFirstHeaderOrNull(AtmosHeaders.LISTABLE_META)) : ImmutableMap. of(); Iterable tags = (from.getFirstHeaderOrNull(AtmosHeaders.TAGS) != null) ? Splitter.on(", ").split( from.getFirstHeaderOrNull(AtmosHeaders.TAGS)) : ImmutableSet. of(); Iterable listableTags = (from.getFirstHeaderOrNull(AtmosHeaders.LISTABLE_TAGS) != null) ? Splitter .on(", ").split(from.getFirstHeaderOrNull(AtmosHeaders.LISTABLE_TAGS)) : ImmutableSet. of(); return new UserMetadata(meta, listableMeta, tags, listableTags); } private static Map getMetaMap(String meta) { return Splitter.on(", ").withKeyValueSeparator('=').split(meta); } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/functions/ReturnTrueIfGroupACLIsOtherRead.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.functions; import static com.google.common.base.Preconditions.checkNotNull; import jakarta.inject.Singleton; import org.jclouds.http.HttpResponse; import com.google.common.base.Function; @Singleton public class ReturnTrueIfGroupACLIsOtherRead implements Function { public Boolean apply(HttpResponse from) { checkNotNull(from, "http response"); return from.getHeaders().containsEntry("x-emc-groupacl", "other=READ"); } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/handlers/AtmosClientErrorRetryHandler.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.handlers; import jakarta.annotation.Resource; import jakarta.inject.Named; import org.jclouds.Constants; import org.jclouds.atmos.domain.AtmosError; import org.jclouds.atmos.reference.AtmosErrorCode; import org.jclouds.atmos.util.AtmosUtils; import org.jclouds.http.HttpCommand; import org.jclouds.http.HttpException; import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpRetryHandler; import org.jclouds.http.HttpUtils; import org.jclouds.http.handlers.BackoffLimitedRetryHandler; import org.jclouds.logging.Logger; import com.google.inject.Inject; /** * Handles Retryable responses with error codes in the 4xx range * * @see Error codes section at */ public class AtmosClientErrorRetryHandler implements HttpRetryHandler { private final AtmosUtils utils; private final BackoffLimitedRetryHandler backoffHandler; @Inject public AtmosClientErrorRetryHandler(BackoffLimitedRetryHandler backoffHandler, AtmosUtils utils) { this.backoffHandler = backoffHandler; this.utils = utils; } @Inject(optional = true) @Named(Constants.PROPERTY_MAX_RETRIES) private int retryCountLimit = 5; @Resource protected Logger logger = Logger.NULL; public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) { if (command.getFailureCount() > retryCountLimit) return false; if (response.getStatusCode() == 404 && command.getCurrentRequest().getMethod().equals("DELETE")) { command.incrementFailureCount(); return true; } else if (response.getStatusCode() == 409) { byte[] content = HttpUtils.closeClientButKeepContentStream(response); // Content can be null in the case of HEAD requests if (content != null) { try { AtmosError error = utils.parseAtmosErrorFromContent(command, response, new String(content)); if (error.getCode() == AtmosErrorCode.CONFLICTING_OPERATION.getCode()) { return backoffHandler.shouldRetryRequest(command, response); } // don't increment count before here, since backoff handler does already command.incrementFailureCount(); } catch (HttpException e) { logger.warn(e, "error parsing response: %s", new String(content)); } } else { command.incrementFailureCount(); } return true; } return false; } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/handlers/AtmosServerErrorRetryHandler.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.handlers; import jakarta.annotation.Resource; import jakarta.inject.Named; import org.jclouds.Constants; import org.jclouds.atmos.domain.AtmosError; import org.jclouds.atmos.reference.AtmosErrorCode; import org.jclouds.atmos.util.AtmosUtils; import org.jclouds.http.HttpCommand; import org.jclouds.http.HttpException; import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpRetryHandler; import org.jclouds.http.HttpUtils; import org.jclouds.http.handlers.BackoffLimitedRetryHandler; import org.jclouds.logging.Logger; import com.google.inject.Inject; /** * Handles Retryable responses with error codes in the 5xx range * * @see Error codes section at */ public class AtmosServerErrorRetryHandler implements HttpRetryHandler { private final AtmosUtils utils; private final BackoffLimitedRetryHandler backoffHandler; @Inject public AtmosServerErrorRetryHandler(BackoffLimitedRetryHandler backoffHandler, AtmosUtils utils) { this.backoffHandler = backoffHandler; this.utils = utils; } @Inject(optional = true) @Named(Constants.PROPERTY_MAX_RETRIES) private int retryCountLimit = 5; @Resource protected Logger logger = Logger.NULL; public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) { if (command.getFailureCount() > retryCountLimit) { return false; } if (response.getStatusCode() == 500) { byte[] content = HttpUtils.closeClientButKeepContentStream(response); // Content can be null in the case of HEAD requests if (content != null) { try { AtmosError error = utils.parseAtmosErrorFromContent(command, response, new String(content)); if (error.getCode() == AtmosErrorCode.SERVER_BUSY.getCode()) { return backoffHandler.shouldRetryRequest(command, response); } // don't increment count before here, since backoff handler does already command.incrementFailureCount(); } catch (HttpException e) { logger.warn(e, "error parsing response: %s", new String(content)); } } else { command.incrementFailureCount(); } return false; } return false; } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/handlers/ParseAtmosErrorFromXmlContent.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.handlers; import static org.jclouds.http.HttpUtils.releasePayload; import java.io.File; import java.io.IOException; import java.util.regex.Matcher; import java.util.regex.Pattern; import jakarta.annotation.Resource; import jakarta.inject.Inject; import jakarta.inject.Singleton; import org.jclouds.atmos.AtmosResponseException; import org.jclouds.atmos.domain.AtmosError; import org.jclouds.atmos.reference.AtmosErrorCode; import org.jclouds.atmos.util.AtmosUtils; import org.jclouds.blobstore.ContainerNotFoundException; import org.jclouds.blobstore.KeyAlreadyExistsException; import org.jclouds.blobstore.KeyNotFoundException; import org.jclouds.http.HttpCommand; import org.jclouds.http.HttpErrorHandler; import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponseException; import org.jclouds.logging.Logger; import org.jclouds.rest.AuthorizationException; import org.jclouds.util.Strings2; /** * This will parse and set an appropriate exception on the command object. * * @see AtmosError */ @Singleton public class ParseAtmosErrorFromXmlContent implements HttpErrorHandler { @Resource protected Logger logger = Logger.NULL; private final AtmosUtils utils; @Inject public ParseAtmosErrorFromXmlContent(AtmosUtils utils) { this.utils = utils; } public static final Pattern DIRECTORY_PATH = Pattern.compile("^/rest/namespace/?([^/]+)/$"); public static final Pattern DIRECTORY_KEY_PATH = Pattern.compile("^/rest/namespace/?([^/]+)/(.*)"); public void handleError(HttpCommand command, HttpResponse response) { Exception exception = new HttpResponseException(command, response); try { AtmosError error = null; if (response.getPayload() != null) { try { String content = Strings2.toStringAndClose(response.getPayload().openStream()); if (content != null && content.indexOf('<') >= 0) { error = utils.parseAtmosErrorFromContent(command, response, Strings2.toInputStream(content)); } else { exception = content != null ? new HttpResponseException(command, response, content) : exception; } } catch (IOException e) { logger.warn(e, "exception reading error from response", response); } } if (error != null && error.getCode() == AtmosErrorCode.RESOURCE_ALREADY_EXISTS.getCode()) { File file = new File(command.getCurrentRequest().getEndpoint().getPath()); exception = new KeyAlreadyExistsException(file.getParentFile().getAbsolutePath(), file.getName()); } else { switch (response.getStatusCode()) { case 401: exception = new AuthorizationException(exception.getMessage(), exception); break; case 404: if (!command.getCurrentRequest().getMethod().equals("DELETE")) { String message = error != null ? error.getMessage() : String.format("%s -> %s", command.getCurrentRequest() .getRequestLine(), response.getStatusLine()); String path = command.getCurrentRequest().getEndpoint().getPath(); Matcher matcher = DIRECTORY_PATH.matcher(path); if (matcher.find()) { exception = new ContainerNotFoundException(matcher.group(1), message); } else { matcher = DIRECTORY_KEY_PATH.matcher(path); if (matcher.find()) { exception = new KeyNotFoundException(matcher.group(1), matcher.group(2), message); } } } break; default: exception = error != null ? new AtmosResponseException(command, response, error) : new HttpResponseException(command, response); } } } finally { releasePayload(response); command.setException(exception); } } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/options/ListOptions.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.options; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; import java.util.Collection; import org.jclouds.http.options.BaseHttpRequestOptions; import com.google.common.collect.ImmutableList; /** * Options used to control paginated results (aka list commands). */ public class ListOptions extends BaseHttpRequestOptions { public static final ListOptions NONE = new ListOptions(); private static final Collection INCLUDE_META = ImmutableList.of(Integer.toString(1)); /** * specifies the position to resume listing *

* note this is an opaque value and should not be interpreted. */ public ListOptions token(String token) { this.headers.put("x-emc-token", checkNotNull(token, "x-emc-token")); return this; } public String getToken() { return getFirstHeaderOrNull("x-emc-token"); } /** * the maximum number of items that should be returned. If this is not specified, there is no * limit. */ public ListOptions limit(int maxresults) { checkState(maxresults >= 0, "maxresults must be >= 0"); checkState(maxresults <= 10000, "maxresults must be <= 10000"); headers.put("x-emc-limit", Integer.toString(maxresults)); return this; } /** * the maximum number of items that should be returned. If this is not specified, there is no * limit. */ public ListOptions includeMeta() { headers.replaceValues("x-emc-include-meta", INCLUDE_META); return this; } public boolean metaIncluded() { String meta = getFirstHeaderOrNull("x-emc-include-meta"); return (meta != null) ? meta.equals("1") : false; } public Integer getLimit() { String maxresults = getFirstHeaderOrNull("x-emc-limit"); return (maxresults != null) ? Integer.valueOf(maxresults) : null; } public static class Builder { /** * @see ListOptions#token(String) */ public static ListOptions token(String token) { ListOptions options = new ListOptions(); return options.token(token); } /** * @see ListOptions#includeMeta() */ public static ListOptions includeMeta() { ListOptions options = new ListOptions(); return options.includeMeta(); } /** * @see ListOptions#limit(int) */ public static ListOptions limit(int maxKeys) { ListOptions options = new ListOptions(); return options.limit(maxKeys); } } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/options/PutOptions.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.options; import org.jclouds.http.options.BaseHttpRequestOptions; /** * Contains options supported in the REST API for the PUT operations. *

*

* Usage

The recommended way to instantiate a PutOptions object is to statically import * PutOptions.Builder.* and invoke a static creation method followed by an instance mutator (if * needed): *

* * import org.jclouds.atmos.options.PutOptions.Builder.* * import org.jclouds.atmos.AtmosClient; * * AtmosClient connection = // get connection * connection.createDirectory("directory", publicRead()); * */ public class PutOptions extends BaseHttpRequestOptions { public static final PutOptions NONE = new PutOptions(); /** * Add public access to all users * */ public PutOptions publicRead() { this.replaceHeader("x-emc-useracl", "root=FULL_CONTROL"); this.replaceHeader("x-emc-groupacl", "other=READ"); return this; } public PutOptions publicNone() { this.replaceHeader("x-emc-useracl", "root=FULL_CONTROL"); this.replaceHeader("x-emc-groupacl", "other=NONE"); return this; } /** * By default Atmos does not allow overwriting objects. * * Note: older versions of Atmos do not support this header. */ public PutOptions overwrite() { this.replaceHeader("x-emc-force-overwrite", "true"); return this; } public static class Builder { /** * @see PutOptions#publicRead */ public static PutOptions publicRead() { PutOptions options = new PutOptions(); return options.publicRead(); } public static PutOptions publicNone() { PutOptions options = new PutOptions(); return options.publicNone(); } public static PutOptions overwrite() { PutOptions options = new PutOptions(); return options.overwrite(); } } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/reference/AtmosErrorCode.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.reference; /** Atmos error codes. */ public enum AtmosErrorCode { /** Operation aborted because of a conflicting operation in progess against the resource. */ CONFLICTING_OPERATION(1006), /** The directory you are attempting to delete is not empty. */ DIRECTORY_NOT_EMPTY(1023), /** The requested object was not found. */ OBJECT_NOT_FOUND(1003), /** The resource you are trying to create already exists. */ RESOURCE_ALREADY_EXISTS(1016), /** The server is busy. Please try again. */ SERVER_BUSY(1040), /** There was a mismatch between the signature in the request and the signature as computed by the server. */ SIGNATURE_MISMATCH(1032); private final int code; private AtmosErrorCode(int code) { this.code = code; } public int getCode() { return code; } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/reference/AtmosHeaders.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.reference; /** * Query parameters common to Atmos apis. * * @see */ public final class AtmosHeaders { public static final String SIGNATURE = "x-emc-signature"; public static final String LISTABLE_META = "x-emc-listable-meta"; public static final String META = "x-emc-meta"; public static final String LISTABLE_TAGS = "x-emc-listable-tags"; public static final String TAGS = "x-emc-tags"; public static final String USER_ACL = "x-emc-useracl"; public static final String DATE = "x-emc-date"; public static final String GROUP_ACL = "x-emc-groupacl"; public static final String UID = "x-emc-uid"; public static final String TOKEN = "x-emc-token"; public static final String CHECKSUM = "x-emc-wschecksum"; private AtmosHeaders() { throw new AssertionError("intentionally unimplemented"); } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/util/AtmosUtils.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.util; import static com.google.common.base.Preconditions.checkState; import static org.jclouds.util.Predicates2.retry; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.net.URI; import jakarta.inject.Inject; import jakarta.inject.Provider; import org.jclouds.atmos.AtmosClient; import org.jclouds.atmos.blobstore.functions.BlobToObject; import org.jclouds.atmos.domain.AtmosError; import org.jclouds.atmos.domain.AtmosObject; import org.jclouds.atmos.filters.SignRequest; import org.jclouds.atmos.options.PutOptions; import org.jclouds.atmos.reference.AtmosErrorCode; import org.jclouds.atmos.xml.ErrorHandler; import org.jclouds.blobstore.ContainerNotFoundException; import org.jclouds.blobstore.KeyAlreadyExistsException; import org.jclouds.blobstore.domain.Blob; import org.jclouds.crypto.Crypto; import org.jclouds.http.HttpCommand; import org.jclouds.http.HttpException; import org.jclouds.http.HttpResponse; import org.jclouds.http.functions.ParseSax; import com.google.common.base.Predicate; /** * Encryption, Hashing, and IO Utilities needed to sign and verify Atmos Storage requests and * responses. */ public class AtmosUtils { @Inject SignRequest signer; @Inject ParseSax.Factory factory; @Inject Provider errorHandlerProvider; public AtmosError parseAtmosErrorFromContent(HttpCommand command, HttpResponse response, InputStream content) throws HttpException { AtmosError error = factory.create(errorHandlerProvider.get()).parse(content); if (error.getCode() == AtmosErrorCode.SIGNATURE_MISMATCH.getCode()) { error.setStringSigned(signer.createStringToSign(command.getCurrentRequest())); } return error; } public static String putBlob(final AtmosClient sync, Crypto crypto, BlobToObject blob2Object, String container, Blob blob, PutOptions options) { final String path = container + "/" + blob.getMetadata().getName(); final AtmosObject object = blob2Object.apply(blob); URI uri; try { uri = sync.createFile(container, object, options); } catch (KeyAlreadyExistsException e) { deletePathAndEnsureGone(sync, path); uri = sync.createFile(container, object, options); } // return object ID as the ETag String objectId = uri.getPath(); String prefix = "/rest/objects/"; checkState(objectId.startsWith(prefix), objectId); return objectId.substring(prefix.length()); } public static void deletePathAndEnsureGone(final AtmosClient sync, String path) { checkState(retry(new Predicate() { public boolean apply(String in) { try { sync.deletePath(in); return !sync.pathExists(in); } catch (ContainerNotFoundException e) { return true; } } }, 3000).apply(path), "%s still exists after deleting!", path); } public AtmosError parseAtmosErrorFromContent(HttpCommand command, HttpResponse response, String content) throws HttpException { return parseAtmosErrorFromContent(command, response, new ByteArrayInputStream(content.getBytes())); } public static String adjustContainerIfDirOptionPresent(String container, org.jclouds.blobstore.options.ListContainerOptions options) { if (options != org.jclouds.blobstore.options.ListContainerOptions.NONE) { // if (options.isRecursive()) { // throw new UnsupportedOperationException("recursive not currently supported in emcsaas"); // } if (options.getDir() != null) { container = container + "/" + options.getDir(); } } return container; } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/xml/ErrorHandler.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.xml; import org.jclouds.atmos.domain.AtmosError; import org.jclouds.http.functions.ParseSax; /** * Parses the error from the Atmos Online Storage REST API. */ public class ErrorHandler extends ParseSax.HandlerWithResult { private StringBuilder currentText = new StringBuilder(); private int code; private String message; public AtmosError getResult() { return new AtmosError(code, message); } public void endElement(String uri, String name, String qName) { if (qName.equals("Code")) { this.code = Integer.parseInt(currentText.toString().trim()); } else if (qName.equals("Message")) { this.message = currentText.toString().trim(); } currentText.setLength(0); } public void characters(char[] ch, int start, int length) { currentText.append(ch, start, length); } } ================================================ FILE: apis/atmos/src/main/java/org/jclouds/atmos/xml/ListDirectoryResponseHandler.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.xml; import java.util.Date; import java.util.Set; import jakarta.inject.Inject; import org.jclouds.atmos.domain.DirectoryEntry; import org.jclouds.atmos.domain.FileType; import org.jclouds.date.DateService; import org.jclouds.http.functions.ParseSax; import com.google.common.collect.Sets; /** * Parses an object list *

* * @see */ public class ListDirectoryResponseHandler extends ParseSax.HandlerWithResult> { private Set entries = Sets.newLinkedHashSet(); private String currentObjectId; private FileType currentType; private String currentFileName; private long currentSize; private Date currentModificationTime; // metadata parsing private String currentName; private StringBuilder currentText = new StringBuilder(); private final DateService dateService; @Inject ListDirectoryResponseHandler(DateService dateService) { this.dateService = dateService; } public Set getResult() { return entries; } public void endElement(String uri, String name, String qName) { if (qName.equals("ObjectID")) { currentObjectId = currentText.toString().trim(); } else if (qName.equals("FileType")) { currentType = FileType.fromValue(currentText.toString().trim()); } else if (qName.equals("Filename")) { currentFileName = currentText.toString().trim(); if (currentFileName.equals("")) currentFileName = null; } else if (qName.equals("Name")) { currentName = currentText.toString().trim(); } else if (qName.equals("Value")) { if (currentName.equals("size")) { currentSize = Long.parseLong(currentText.toString().trim()); } else if (currentName.equals("mtime")) { currentModificationTime = dateService.iso8601DateOrSecondsDateParse(currentText.toString().trim()); } } else if (qName.equals("DirectoryEntry")) { entries.add(new DirectoryEntry(currentObjectId, currentType, currentFileName, currentSize, currentModificationTime)); } currentText.setLength(0); } public void characters(char[] ch, int start, int length) { currentText.append(ch, start, length); } } ================================================ FILE: apis/atmos/src/test/java/org/jclouds/atmos/AtmosApiMetadataTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos; import org.jclouds.blobstore.internal.BaseBlobStoreApiMetadataTest; import org.testng.annotations.Test; @Test(groups = "unit", testName = "AtmosApiMetadataTest") public class AtmosApiMetadataTest extends BaseBlobStoreApiMetadataTest { public AtmosApiMetadataTest() { super(new AtmosApiMetadata()); } } ================================================ FILE: apis/atmos/src/test/java/org/jclouds/atmos/AtmosClientLiveTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos; import static com.google.common.base.Charsets.UTF_8; import static com.google.common.base.Preconditions.checkState; import static org.jclouds.util.Predicates2.retry; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNull; import java.io.IOException; import java.lang.reflect.UndeclaredThrowableException; import java.net.URI; import java.security.SecureRandom; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; import org.jclouds.atmos.domain.AtmosObject; import org.jclouds.atmos.domain.BoundedSet; import org.jclouds.atmos.domain.DirectoryEntry; import org.jclouds.atmos.domain.FileType; import org.jclouds.atmos.domain.SystemMetadata; import org.jclouds.atmos.options.ListOptions; import org.jclouds.blobstore.ContainerNotFoundException; import org.jclouds.blobstore.KeyAlreadyExistsException; import org.jclouds.blobstore.KeyNotFoundException; import org.jclouds.blobstore.integration.internal.BaseBlobStoreIntegrationTest; import org.jclouds.http.HttpResponseException; import org.jclouds.io.Payloads; import org.jclouds.io.payloads.InputStreamPayload; import org.jclouds.util.Strings2; import org.testng.annotations.Test; import com.google.common.base.Predicate; import com.google.common.base.Throwables; import com.google.common.collect.Iterables; import com.google.common.collect.Sets; import com.google.common.hash.HashCode; import com.google.common.hash.Hashing; /** * Tests behavior of {@code AtmosClient} */ @Test(groups = "live", singleThreaded = true) public class AtmosClientLiveTest extends BaseBlobStoreIntegrationTest { public AtmosClientLiveTest() { provider = "atmos"; } public AtmosClient getApi() { return view.unwrapApi(AtmosClient.class); } private static final class HeadMatches implements Runnable { private final AtmosClient connection; private final String name; private final String metadataValue; private HeadMatches(AtmosClient connection, String name, String metadataValue) { this.connection = connection; this.name = name; this.metadataValue = metadataValue; } public void run() { try { verifyHeadObject(connection, name, metadataValue); } catch (Exception e) { throw new AssertionError(e); } } } private static final class ObjectMatches implements Runnable { private final AtmosClient connection; private final String name; private final String metadataValue; private final String compare; private ObjectMatches(AtmosClient connection, String name, String metadataValue, String compare) { this.connection = connection; this.name = name; this.metadataValue = metadataValue; this.compare = compare; } public void run() { try { verifyObject(connection, name, compare, metadataValue); } catch (Exception e) { throw new AssertionError(e); } } } private static final int INCONSISTENCY_WINDOW = 5000; private String containerPrefix = BaseBlobStoreIntegrationTest.CONTAINER_PREFIX + "live"; URI container1; URI container2; @Test public void testListDirectorys() throws Exception { BoundedSet response = getApi().listDirectories(); assert null != response; } String privateDirectory; String publicDirectory; @Test(timeOut = 5 * 60 * 1000) public void testCreateDirectory() throws Exception { boolean created = false; while (!created) { privateDirectory = containerPrefix + new SecureRandom().nextInt(); try { created = getApi().createDirectory(privateDirectory) != null; } catch (UndeclaredThrowableException e) { HttpResponseException htpe = (HttpResponseException) e.getCause().getCause(); if (htpe.getResponse().getStatusCode() == 409) continue; throw e; } } BoundedSet response = getApi().listDirectories(); for (DirectoryEntry id : response) { BoundedSet r2 = getApi().listDirectory(id.getObjectName()); assert r2 != null; } // subsequent creation should fail assertNull(getApi().createDirectory(privateDirectory)); } @Test(timeOut = 5 * 60 * 1000, dependsOnMethods = { "testCreateDirectory" }) public void testListOptions() throws Exception { String data = "here is my data!"; HashCode hashCode = Hashing.md5().hashString(data, UTF_8); createOrReplaceObject("object2", data, hashCode, "meta-value1"); createOrReplaceObject("object3", data, hashCode, "meta-value1"); createOrReplaceObject("object4", data, hashCode, "meta-value1"); BoundedSet r2 = getApi().listDirectory(privateDirectory, ListOptions.Builder.limit(1)); assertEquals(r2.size(), 1); assert r2.getToken() != null; assertEquals(Iterables.getLast(Sets.newTreeSet(r2)).getObjectName(), "object2"); r2 = getApi().listDirectory(privateDirectory, ListOptions.Builder.token(r2.getToken())); assertEquals(r2.size(), 2); assert r2.getToken() == null; assertEquals(Iterables.getLast(Sets.newTreeSet(r2)).getObjectName(), "object4"); } @Test(timeOut = 5 * 60 * 1000, dependsOnMethods = { "testListOptions" }) public void testFileOperations() throws Exception { // create the object System.err.printf("creating%n"); String data1 = "here is my data!"; createOrReplaceObject("object", data1, Hashing.md5().hashString(data1, UTF_8), "meta-value1"); assertEventuallyObjectMatches("object", "here is my data!", "meta-value1"); assertEventuallyHeadMatches("object", "meta-value1"); // try overwriting the object System.err.printf("overwriting%n"); String data2 = "here is my data?"; createOrReplaceObject("object", data2, Hashing.md5().hashString(data2, UTF_8), "meta-value?"); assertEventuallyObjectMatches("object", "here is my data?", "meta-value?"); for (boolean stream : new boolean[] { true, false }) { System.err.printf("upload/delete/create type %s%n", stream ? "stream" : "string"); // try updating createOrUpdateWithErrorLoop(stream, "there is my data", "2"); deleteConfirmed(privateDirectory + "/object"); // now create createOrUpdateWithErrorLoop(stream, "where is my data", "3"); } } @Test(timeOut = 5 * 60 * 1000, dependsOnMethods = { "testFileOperations" }) public void testPutZeroLengthBlob() throws Exception { AtmosObject object = getApi().newObject(); object.getContentMetadata().setName("object"); byte[] payload = new byte[0]; object.setPayload(Payloads.newPayload(payload)); object.getContentMetadata().setContentLength(Long.valueOf(payload.length)); replaceObject(object); } private void createOrUpdateWithErrorLoop(boolean stream, String data, String metadataValue) throws Exception { createOrReplaceObject("object", makeData(data, stream), Hashing.md5().hashString(data, UTF_8), metadataValue); assertEventuallyObjectMatches("object", data, metadataValue); } Object makeData(String in, boolean stream) { return stream ? Strings2.toInputStream(in) : in; } private void createOrReplaceObject(String name, Object data, HashCode hashCode, String metadataValue) throws Exception { // Test PUT with string data, ETag hash, and a piece of metadata AtmosObject object = getApi().newObject(); object.getContentMetadata().setName(name); object.setPayload(Payloads.newPayload(data)); object.getContentMetadata().setContentLength(16L); object.getContentMetadata().setContentMD5(hashCode.asBytes()); object.getContentMetadata().setContentType("text/plain"); object.getUserMetadata().getMetadata().put("Metadata", metadataValue); replaceObject(object); } /** * Due to eventual consistency, container commands may not return correctly immediately. Hence, * we will try up to the inconsistency window to see if the assertion completes. */ protected static void assertEventually(Runnable assertion) throws InterruptedException { long start = System.currentTimeMillis(); AssertionError error = null; for (int i = 0; i < 30; i++) { try { assertion.run(); if (i > 0) System.err.printf("%d attempts and %dms asserting %s%n", i + 1, System.currentTimeMillis() - start, assertion.getClass().getSimpleName()); return; } catch (AssertionError e) { error = e; } Thread.sleep(INCONSISTENCY_WINDOW / 30); } if (error != null) throw error; } protected void assertEventuallyObjectMatches(final String name, final String compare, final String metadataValue) throws InterruptedException { assertEventually(new ObjectMatches(getApi(), privateDirectory + "/" + name, metadataValue, compare)); } protected void assertEventuallyHeadMatches(final String name, final String metadataValue) throws InterruptedException { assertEventually(new HeadMatches(getApi(), privateDirectory + "/" + name, metadataValue)); } private static void verifyHeadObject(AtmosClient connection, String path, String metadataValue) throws InterruptedException, ExecutionException, TimeoutException, IOException { AtmosObject getBlob = connection.headFile(path); assertEquals(Strings2.toStringAndClose(getBlob.getPayload().openStream()), ""); verifyMetadata(metadataValue, getBlob); } private static void verifyObject(AtmosClient connection, String path, String compare, String metadataValue) throws InterruptedException, ExecutionException, TimeoutException, IOException { AtmosObject getBlob = connection.readFile(path); assertEquals(Strings2.toStringAndClose(getBlob.getPayload().openStream()), compare); verifyMetadata(metadataValue, getBlob); } private static void verifyMetadata(String metadataValue, AtmosObject getBlob) { assertEquals(getBlob.getContentMetadata().getContentLength(), Long.valueOf(16)); assert getBlob.getContentMetadata().getContentType().startsWith("text/plain"); assertEquals(getBlob.getUserMetadata().getMetadata().get("Metadata"), metadataValue); SystemMetadata md = getBlob.getSystemMetadata(); assertEquals(md.getSize(), 16); assert md.getGroupID() != null; assertEquals(md.getHardLinkCount(), 1); assert md.getInceptionTime() != null; assert md.getLastAccessTime() != null; assert md.getLastMetadataModification() != null; assert md.getLastUserDataModification() != null; assert md.getObjectID() != null; assertEquals(md.getObjectName(), "object"); assert md.getPolicyName() != null; assertEquals(md.getType(), FileType.REGULAR); assert md.getUserID() != null; } private void replaceObject(AtmosObject object) throws Exception { alwaysDeleteFirstReplaceStrategy(object); // retryAndCheckSystemMetadataAndPutIfPresentReplaceStrategy(object); // HEAD 200 followed by // PUT = 404! } private void alwaysDeleteFirstReplaceStrategy(AtmosObject object) throws Exception { deleteConfirmed(privateDirectory + "/" + object.getContentMetadata().getName()); long time = System.currentTimeMillis(); try { getApi().createFile(privateDirectory, object); System.err.printf("%s %s; %dms%n", "created", object.getPayload() instanceof InputStreamPayload ? "stream" : "string", System.currentTimeMillis() - time); } catch (Exception e) { String message = Throwables.getRootCause(e).getMessage(); System.err.printf("failure %s %s; %dms: [%s]%n", "creating", object.getPayload() instanceof InputStreamPayload ? "stream" : "string", System.currentTimeMillis() - time, message); throw e; } } private void deleteConfirmed(final String path) throws InterruptedException, ExecutionException, TimeoutException { long time = System.currentTimeMillis(); deleteConsistencyAware(path); System.err.printf("confirmed deletion after %dms%n", System.currentTimeMillis() - time); } protected void deleteImmediateAndVerifyWithHead(final String path) throws InterruptedException, ExecutionException, TimeoutException { try { getApi().deletePath(path); } catch (KeyNotFoundException ex) { } assert !getApi().pathExists(path); System.err.printf("path %s doesn't exist%n", path); assert !getApi().pathExists(path); System.err.printf("path %s doesn't exist%n", path); } protected void deleteConsistencyAware(String path) throws InterruptedException, ExecutionException, TimeoutException { try { getApi().deletePath(path); } catch (KeyNotFoundException ex) { } checkState(retry(new Predicate() { public boolean apply(String in) { try { return !getApi().pathExists(in); } catch (ContainerNotFoundException e) { return true; } } }, INCONSISTENCY_WINDOW).apply(path), "%s still exists after deleting!", path); } protected void retryAndCheckSystemMetadataAndPutIfPresentReplaceStrategy(AtmosObject object) throws Exception { int failures = 0; while (true) { try { checkSystemMetadataAndPutIfPresentReplaceStrategy(object); break; } catch (ExecutionException e1) {// bug if (!(e1.getCause() instanceof KeyAlreadyExistsException)) throw e1; else failures++; } } if (failures > 0) System.err.printf("%d failures create/replacing %s%n", failures, object.getPayload() instanceof InputStreamPayload ? "stream" : "string"); } private void checkSystemMetadataAndPutIfPresentReplaceStrategy(AtmosObject object) throws Exception { long time = System.currentTimeMillis(); boolean update = true; try { getApi().getSystemMetadata(privateDirectory + "/object"); } catch (KeyNotFoundException ex) { update = false; } try { if (update) getApi().updateFile(privateDirectory, object); else getApi().createFile(privateDirectory, object); System.err.printf("%s %s; %dms%n", update ? "updated" : "created", object.getPayload() instanceof InputStreamPayload ? "stream" : "string", System.currentTimeMillis() - time); } catch (Exception e) { String message = Throwables.getRootCause(e).getMessage(); System.err.printf("failure %s %s; %dms: [%s]%n", update ? "updating" : "creating", object.getPayload() instanceof InputStreamPayload ? "stream" : "string", System.currentTimeMillis() - time, message); throw e; } } } ================================================ FILE: apis/atmos/src/test/java/org/jclouds/atmos/AtmosClientTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos; import static org.jclouds.reflect.Reflection2.method; import static org.testng.Assert.assertEquals; import java.io.IOException; import org.jclouds.Fallbacks.FalseOnNotFoundOr404; import org.jclouds.Fallbacks.NullOnNotFoundOr404; import org.jclouds.apis.ApiMetadata; import org.jclouds.atmos.blobstore.functions.BlobToObject; import org.jclouds.atmos.config.AtmosHttpApiModule; import org.jclouds.atmos.domain.AtmosObject; import org.jclouds.atmos.fallbacks.TrueOn404FalseOnPathNotEmpty; import org.jclouds.atmos.filters.SignRequest; import org.jclouds.atmos.functions.ParseDirectoryListFromContentAndHeaders; import org.jclouds.atmos.functions.ParseObjectFromHeadersAndHttpContent; import org.jclouds.atmos.functions.ParseSystemMetadataFromHeaders; import org.jclouds.atmos.functions.ReturnTrueIfGroupACLIsOtherRead; import org.jclouds.atmos.options.ListOptions; import org.jclouds.atmos.options.PutOptions; import org.jclouds.blobstore.BlobStoreFallbacks.NullOnKeyAlreadyExists; import org.jclouds.blobstore.BlobStoreFallbacks.ThrowContainerNotFoundOn404; import org.jclouds.blobstore.BlobStoreFallbacks.ThrowKeyNotFoundOn404; import org.jclouds.blobstore.binders.BindBlobToMultipartFormTest; import org.jclouds.date.TimeStamp; import org.jclouds.http.HttpRequest; import org.jclouds.http.functions.ParseURIFromListOrLocationHeaderIf20x; import org.jclouds.http.functions.ReleasePayloadAndReturn; import org.jclouds.http.functions.ReturnTrueIf2xx; import org.jclouds.http.options.GetOptions; import org.jclouds.rest.ConfiguresHttpApi; import org.jclouds.rest.internal.BaseRestAnnotationProcessingTest; import org.jclouds.rest.internal.GeneratedHttpRequest; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import com.google.common.base.Supplier; import com.google.common.collect.ImmutableList; import com.google.common.net.HttpHeaders; import com.google.common.reflect.Invokable; import com.google.inject.Module; @Test(groups = "unit", testName = "AtmosClientTest") public class AtmosClientTest extends BaseRestAnnotationProcessingTest { private BlobToObject blobToObject; public void testListDirectories() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(AtmosClient.class, "listDirectories", ListOptions[].class); GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.of()); assertRequestLineEquals(request, "GET https://accesspoint.atmosonline.com/rest/namespace/ HTTP/1.1"); assertNonPayloadHeadersEqual(request, HttpHeaders.ACCEPT + ": text/xml\n"); assertPayloadEquals(request, null, null, false); assertResponseParserClassEquals(method, request, ParseDirectoryListFromContentAndHeaders.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, null); checkFilters(request); } public void testListDirectory() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(AtmosClient.class, "listDirectory", String.class, ListOptions[].class); GeneratedHttpRequest request = processor.createRequest(method, ImmutableList. of("directory")); assertRequestLineEquals(request, "GET https://accesspoint.atmosonline.com/rest/namespace/directory/ HTTP/1.1"); assertNonPayloadHeadersEqual(request, HttpHeaders.ACCEPT + ": text/xml\nx-emc-include-meta: 1\n"); assertPayloadEquals(request, null, null, false); assertResponseParserClassEquals(method, request, ParseDirectoryListFromContentAndHeaders.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, ThrowContainerNotFoundOn404.class); checkFilters(request); } public void testListDirectoriesOptions() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(AtmosClient.class, "listDirectories", ListOptions[].class); GeneratedHttpRequest request = processor.createRequest(method, ImmutableList. of(new ListOptions().limit(1).token("asda"))); assertRequestLineEquals(request, "GET https://accesspoint.atmosonline.com/rest/namespace/ HTTP/1.1"); assertNonPayloadHeadersEqual(request, HttpHeaders.ACCEPT + ": text/xml\nx-emc-limit: 1\nx-emc-token: asda\n"); assertPayloadEquals(request, null, null, false); assertResponseParserClassEquals(method, request, ParseDirectoryListFromContentAndHeaders.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, null); checkFilters(request); } public void testListDirectoryOptions() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(AtmosClient.class, "listDirectory", String.class, ListOptions[].class); GeneratedHttpRequest request = processor.createRequest(method, ImmutableList. of("directory", new ListOptions().limit(1).token("asda"))); assertRequestLineEquals(request, "GET https://accesspoint.atmosonline.com/rest/namespace/directory/ HTTP/1.1"); assertNonPayloadHeadersEqual(request, HttpHeaders.ACCEPT + ": text/xml\nx-emc-include-meta: 1\nx-emc-limit: 1\nx-emc-token: asda\n"); assertPayloadEquals(request, null, null, false); assertResponseParserClassEquals(method, request, ParseDirectoryListFromContentAndHeaders.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, ThrowContainerNotFoundOn404.class); checkFilters(request); } public void testCreateDirectory() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(AtmosClient.class, "createDirectory", String.class, PutOptions[].class); GeneratedHttpRequest request = processor.createRequest(method, ImmutableList. of("dir")); assertRequestLineEquals(request, "POST https://accesspoint.atmosonline.com/rest/namespace/dir/ HTTP/1.1"); assertNonPayloadHeadersEqual(request, HttpHeaders.ACCEPT + ": */*\n"); assertPayloadEquals(request, "", "application/octet-stream", false); assertResponseParserClassEquals(method, request, ParseURIFromListOrLocationHeaderIf20x.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, NullOnKeyAlreadyExists.class); checkFilters(request); } public void testCreateDirectoryOptions() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(AtmosClient.class, "createDirectory", String.class, PutOptions[].class); GeneratedHttpRequest request = processor.createRequest(method, ImmutableList. of("dir", PutOptions.Builder.publicRead())); assertRequestLineEquals(request, "POST https://accesspoint.atmosonline.com/rest/namespace/dir/ HTTP/1.1"); assertNonPayloadHeadersEqual(request, HttpHeaders.ACCEPT + ": */*\nx-emc-groupacl: other=READ\nx-emc-useracl: root=FULL_CONTROL\n"); assertPayloadEquals(request, "", "application/octet-stream", false); assertResponseParserClassEquals(method, request, ParseURIFromListOrLocationHeaderIf20x.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, NullOnKeyAlreadyExists.class); checkFilters(request); } public void testCreateFile() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(AtmosClient.class, "createFile", String.class, AtmosObject.class, PutOptions[].class); GeneratedHttpRequest request = processor.createRequest(method, ImmutableList. of("dir", blobToObject .apply(BindBlobToMultipartFormTest.TEST_BLOB))); assertRequestLineEquals(request, "POST https://accesspoint.atmosonline.com/rest/namespace/dir/hello HTTP/1.1"); assertNonPayloadHeadersEqual(request, HttpHeaders.ACCEPT + ": */*\nExpect: 100-continue\n"); assertPayloadEquals(request, "hello", "text/plain", false); assertResponseParserClassEquals(method, request, ParseURIFromListOrLocationHeaderIf20x.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, null); checkFilters(request); } public void testCreateFileOptions() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(AtmosClient.class, "createFile", String.class, AtmosObject.class, PutOptions[].class); GeneratedHttpRequest request = processor.createRequest(method, ImmutableList. of("dir", blobToObject .apply(BindBlobToMultipartFormTest.TEST_BLOB), PutOptions.Builder.publicRead())); assertRequestLineEquals(request, "POST https://accesspoint.atmosonline.com/rest/namespace/dir/hello HTTP/1.1"); assertNonPayloadHeadersEqual(request, HttpHeaders.ACCEPT + ": */*\nExpect: 100-continue\nx-emc-groupacl: other=READ\nx-emc-useracl: root=FULL_CONTROL\n"); assertPayloadEquals(request, "hello", "text/plain", false); assertResponseParserClassEquals(method, request, ParseURIFromListOrLocationHeaderIf20x.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, null); checkFilters(request); } public void testUpdateFile() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(AtmosClient.class, "updateFile", String.class, AtmosObject.class, PutOptions[].class); GeneratedHttpRequest request = processor.createRequest(method, ImmutableList. of("dir", blobToObject .apply(BindBlobToMultipartFormTest.TEST_BLOB))); assertRequestLineEquals(request, "PUT https://accesspoint.atmosonline.com/rest/namespace/dir/hello HTTP/1.1"); assertNonPayloadHeadersEqual(request, HttpHeaders.ACCEPT + ": */*\nExpect: 100-continue\n"); assertPayloadEquals(request, "hello", "text/plain", false); assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, ThrowKeyNotFoundOn404.class); checkFilters(request); } public void testUpdateFileOptions() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(AtmosClient.class, "updateFile", String.class, AtmosObject.class, PutOptions[].class); GeneratedHttpRequest request = processor.createRequest(method, ImmutableList. of("dir", blobToObject .apply(BindBlobToMultipartFormTest.TEST_BLOB), PutOptions.Builder.publicRead())); assertRequestLineEquals(request, "PUT https://accesspoint.atmosonline.com/rest/namespace/dir/hello HTTP/1.1"); assertNonPayloadHeadersEqual(request, HttpHeaders.ACCEPT + ": */*\nExpect: 100-continue\nx-emc-groupacl: other=READ\nx-emc-useracl: root=FULL_CONTROL\n"); assertPayloadEquals(request, "hello", "text/plain", false); assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, ThrowKeyNotFoundOn404.class); checkFilters(request); } public void testReadFile() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(AtmosClient.class, "readFile", String.class, GetOptions[].class); GeneratedHttpRequest request = processor.createRequest(method, ImmutableList. of("dir/file")); assertRequestLineEquals(request, "GET https://accesspoint.atmosonline.com/rest/namespace/dir/file HTTP/1.1"); assertNonPayloadHeadersEqual(request, HttpHeaders.ACCEPT + ": */*\n"); assertPayloadEquals(request, null, null, false); assertResponseParserClassEquals(method, request, ParseObjectFromHeadersAndHttpContent.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, NullOnNotFoundOr404.class); checkFilters(request); } public void testGetSystemMetadata() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(AtmosClient.class, "getSystemMetadata", String.class); GeneratedHttpRequest request = processor.createRequest(method, ImmutableList. of("dir/file")); assertRequestLineEquals(request, "HEAD https://accesspoint.atmosonline.com/rest/namespace/dir/file HTTP/1.1"); assertNonPayloadHeadersEqual(request, HttpHeaders.ACCEPT + ": */*\n"); assertPayloadEquals(request, null, null, false); assertResponseParserClassEquals(method, request, ParseSystemMetadataFromHeaders.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, NullOnNotFoundOr404.class); checkFilters(request); } public void testDeletePath() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(AtmosClient.class, "deletePath", String.class); GeneratedHttpRequest request = processor.createRequest(method, ImmutableList. of("dir/file")); assertRequestLineEquals(request, "DELETE https://accesspoint.atmosonline.com/rest/namespace/dir/file HTTP/1.1"); assertNonPayloadHeadersEqual(request, HttpHeaders.ACCEPT + ": */*\n"); assertPayloadEquals(request, null, null, false); assertResponseParserClassEquals(method, request, ReturnTrueIf2xx.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, TrueOn404FalseOnPathNotEmpty.class); checkFilters(request); } public void testIsPublic() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(AtmosClient.class, "isPublic", String.class); GeneratedHttpRequest request = processor.createRequest(method, ImmutableList. of("dir/file")); assertRequestLineEquals(request, "HEAD https://accesspoint.atmosonline.com/rest/namespace/dir/file HTTP/1.1"); assertNonPayloadHeadersEqual(request, HttpHeaders.ACCEPT + ": */*\n"); assertPayloadEquals(request, null, null, false); assertResponseParserClassEquals(method, request, ReturnTrueIfGroupACLIsOtherRead.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, FalseOnNotFoundOr404.class); checkFilters(request); } public void testNewObject() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(AtmosClient.class, "newObject"); assertEquals(method.getReturnType().getRawType(), AtmosObject.class); } @Override protected void checkFilters(HttpRequest request) { assertEquals(request.getFilters().size(), 1); assertEquals(request.getFilters().get(0).getClass(), SignRequest.class); } @BeforeClass @Override protected void setupFactory() throws IOException { super.setupFactory(); blobToObject = injector.getInstance(BlobToObject.class); } @Override protected Module createModule() { return new TestAtmosHttpApiModule(); } @ConfiguresHttpApi private static final class TestAtmosHttpApiModule extends AtmosHttpApiModule { @Override protected void configure() { super.configure(); } @Override protected String provideTimeStamp(@TimeStamp Supplier cache) { return "Thu, 05 Jun 2008 16:38:19 GMT"; } } protected String provider = "atmos"; @Override public ApiMetadata createApiMetadata() { return new AtmosApiMetadata(); } } ================================================ FILE: apis/atmos/src/test/java/org/jclouds/atmos/binders/BindMetadataToHeadersTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.binders; import static org.testng.Assert.assertEquals; import java.io.File; import org.jclouds.atmos.domain.AtmosObject; import org.jclouds.http.HttpRequest; import org.jclouds.io.Payload; import org.jclouds.io.Payloads; import org.testng.annotations.Test; import com.google.inject.Guice; import com.google.inject.Injector; /** * Tests behavior of {@code BindMetadataToHeaders} */ @Test(groups = "unit") public class BindMetadataToHeadersTest { Injector injector = Guice.createInjector(); BindMetadataToHeaders binder = injector.getInstance(BindMetadataToHeaders.class); public void testGood() { AtmosObject object = injector.getInstance(AtmosObject.Factory.class).create(null); Payload payload = Payloads.newStringPayload(""); object.setPayload(payload); object.getUserMetadata().getListableMetadata().put("apple", "bear"); object.getUserMetadata().getListableMetadata().put("sushi", "king"); HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://localhost").build(); request = binder.bindToRequest(request, object); assertEquals(request.getFirstHeaderOrNull("x-emc-listable-meta"), "apple=bear,sushi=king"); } @Test(expectedExceptions = IllegalArgumentException.class) public void testMustBeAtmosObject() { HttpRequest request = HttpRequest.builder().method("POST").endpoint("http://localhost").build(); binder.bindToRequest(request, new File("foo")); } @Test(expectedExceptions = NullPointerException.class) public void testNullIsBad() { HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://momma").build(); binder.bindToRequest(request, null); } @Test(expectedExceptions = NullPointerException.class) public void testNullPayloadIsBad() { AtmosObject object = injector.getInstance(AtmosObject.Factory.class).create(null); HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://localhost").build(); binder.bindToRequest(request, object); } @Test(expectedExceptions = IllegalArgumentException.class) public void testNullContentLengthIllegal() { AtmosObject object = injector.getInstance(AtmosObject.Factory.class).create(null); Payload payload = Payloads.newStringPayload(""); payload.getContentMetadata().setContentLength(null); object.setPayload(payload); HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://localhost").build(); binder.bindToRequest(request, object); } } ================================================ FILE: apis/atmos/src/test/java/org/jclouds/atmos/binders/BindUserMetadataToHeadersTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.binders; import static org.testng.Assert.assertEquals; import java.io.File; import org.jclouds.atmos.domain.UserMetadata; import org.jclouds.http.HttpRequest; import org.testng.annotations.Test; import com.google.inject.Guice; import com.google.inject.Injector; /** * Tests behavior of {@code BindUserMetadataToHeaders} */ @Test(groups = "unit") public class BindUserMetadataToHeadersTest { Injector injector = Guice.createInjector(); BindUserMetadataToHeaders binder = injector.getInstance(BindUserMetadataToHeaders.class); public void testMeta() { UserMetadata metadata = new UserMetadata(); metadata.getMetadata().put("apple", "bear"); metadata.getMetadata().put("sushi", "king"); HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://localhost").build(); request = binder.bindToRequest(request, metadata); assertEquals(request.getFirstHeaderOrNull("x-emc-meta"), "apple=bear,sushi=king"); } public void testListableMeta() { UserMetadata metadata = new UserMetadata(); metadata.getListableMetadata().put("apple", "bear"); metadata.getListableMetadata().put("sushi", "king"); HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://localhost").build(); request = binder.bindToRequest(request, metadata); assertEquals(request.getFirstHeaderOrNull("x-emc-listable-meta"), "apple=bear,sushi=king"); } public void testTags() { UserMetadata tagsdata = new UserMetadata(); tagsdata.getTags().add("apple"); tagsdata.getTags().add("sushi"); HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://localhost").build(); request = binder.bindToRequest(request, tagsdata); assertEquals(request.getFirstHeaderOrNull("x-emc-tags"), "apple,sushi"); } public void testListableTags() { UserMetadata tagsdata = new UserMetadata(); tagsdata.getListableTags().add("apple"); tagsdata.getListableTags().add("sushi"); HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://localhost").build(); request = binder.bindToRequest(request, tagsdata); assertEquals(request.getFirstHeaderOrNull("x-emc-listable-tags"), "apple,sushi"); } @Test(expectedExceptions = IllegalArgumentException.class) public void testMustBeUserMetadata() { HttpRequest request = HttpRequest.builder().method("POST").endpoint("http://localhost").build(); binder.bindToRequest(request, new File("foo")); } @Test(expectedExceptions = { NullPointerException.class, IllegalStateException.class }) public void testNullIsBad() { HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://momma").build(); binder.bindToRequest(request, null); } } ================================================ FILE: apis/atmos/src/test/java/org/jclouds/atmos/blobstore/AtmosBlobRequestSignerTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.blobstore; import static org.testng.Assert.assertEquals; import java.io.IOException; import java.util.Date; import org.jclouds.apis.ApiMetadata; import org.jclouds.atmos.AtmosApiMetadata; import org.jclouds.atmos.AtmosClient; import org.jclouds.atmos.config.AtmosHttpApiModule; import org.jclouds.atmos.filters.SignRequest; import org.jclouds.blobstore.BlobRequestSigner; import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.Blob.Factory; import org.jclouds.date.TimeStamp; import org.jclouds.http.HttpRequest; import org.jclouds.rest.ConfiguresHttpApi; import org.jclouds.rest.internal.BaseRestAnnotationProcessingTest; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import com.google.common.base.Supplier; import com.google.common.hash.HashCode; import com.google.inject.Module; /** * Tests behavior of {@code AtmosBlobRequestSigner} */ // NOTE:without testName, this will not call @Before* and fail w/NPE during surefire @Test(groups = "unit", testName = "AtmosBlobRequestSignerTest") public class AtmosBlobRequestSignerTest extends BaseRestAnnotationProcessingTest { public AtmosBlobRequestSignerTest() { // this is base64 decoded in the signer; credential = "aaaabbbb"; } private BlobRequestSigner signer; private Factory blobFactory; public void testSignGetBlob() throws ArrayIndexOutOfBoundsException, SecurityException, IllegalArgumentException, NoSuchMethodException, IOException { HttpRequest request = signer.signGetBlob("container", "name"); assertRequestLineEquals(request, "GET https://accesspoint.atmosonline.com/rest/namespace/container/name?uid=identity&expires=1212684799&signature=oijXdvPjHQ/LwWDcdx9Eozsu77o%3D HTTP/1.1"); assertNonPayloadHeadersEqual(request, ""); assertPayloadEquals(request, null, null, false); assertEquals(request.getFilters().size(), 0); } public void testSignPutBlob() throws ArrayIndexOutOfBoundsException, SecurityException, IllegalArgumentException, NoSuchMethodException, IOException { HashCode hashCode = HashCode.fromBytes(new byte[16]); Blob blob = blobFactory.create(null); blob.getMetadata().setName("name"); blob.setPayload(""); blob.getPayload().getContentMetadata().setContentLength(2L); blob.getPayload().getContentMetadata().setContentMD5(hashCode.asBytes()); blob.getPayload().getContentMetadata().setContentType("text/plain"); blob.getPayload().getContentMetadata().setExpires(new Date(1000)); HttpRequest request = signer.signPutBlob("container", blob); assertRequestLineEquals(request, "POST https://accesspoint.atmosonline.com/rest/namespace/container/name HTTP/1.1"); assertNonPayloadHeadersEqual( request, "Accept: */*\n" + "Date: Thu, 05 Jun 2008 16:38:19 GMT\n" + "Expect: 100-continue\n" + "x-emc-signature: OlAHsoIDCsO5YmqjRxOIM5sp3r0=\n" + "x-emc-uid: identity\n" + "x-emc-wschecksum: MD5/0/00000000000000000000000000000000\n"); assertContentHeadersEqual(request, "text/plain", null, null, null, 2L, hashCode.asBytes(), new Date(1000)); assertEquals(request.getFilters().size(), 0); } @BeforeClass protected void setupFactory() throws IOException { super.setupFactory(); this.blobFactory = injector.getInstance(Blob.Factory.class); this.signer = injector.getInstance(BlobRequestSigner.class); } @Override protected void checkFilters(HttpRequest request) { assertEquals(request.getFilters().size(), 1); assertEquals(request.getFilters().get(0).getClass(), SignRequest.class); } @Override protected Module createModule() { return new TestAtmosHttpApiModule(); } @ConfiguresHttpApi private static final class TestAtmosHttpApiModule extends AtmosHttpApiModule { @Override protected void configure() { super.configure(); } @Override protected String provideTimeStamp(@TimeStamp Supplier cache) { return "Thu, 05 Jun 2008 16:38:19 GMT"; } } @Override public ApiMetadata createApiMetadata() { return new AtmosApiMetadata(); } } ================================================ FILE: apis/atmos/src/test/java/org/jclouds/atmos/blobstore/functions/ListOptionsToBlobStoreListOptions.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.blobstore.functions; import jakarta.inject.Singleton; import org.jclouds.blobstore.options.ListContainerOptions; import com.google.common.base.Function; @Singleton public class ListOptionsToBlobStoreListOptions implements Function { public ListContainerOptions apply(org.jclouds.atmos.options.ListOptions[] optionsList) { ListContainerOptions options = new ListContainerOptions(); if (optionsList.length != 0) { if (optionsList[0].getToken() != null) { options.afterMarker(optionsList[0].getToken()); } if (optionsList[0].getLimit() != null) { options.maxResults(optionsList[0].getLimit()); } if (optionsList[0].metaIncluded()) { options.withDetails(); } } return options; } } ================================================ FILE: apis/atmos/src/test/java/org/jclouds/atmos/blobstore/functions/ResourceMetadataListToDirectoryEntryList.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.blobstore.functions; import jakarta.inject.Singleton; import org.jclouds.atmos.domain.BoundedSet; import org.jclouds.atmos.domain.DirectoryEntry; import org.jclouds.atmos.domain.FileType; import org.jclouds.atmos.domain.internal.BoundedLinkedHashSet; import org.jclouds.blobstore.domain.StorageMetadata; import org.jclouds.blobstore.domain.StorageType; import com.google.common.base.Function; import com.google.common.collect.Iterables; @Singleton public class ResourceMetadataListToDirectoryEntryList implements Function, BoundedSet> { public BoundedSet apply( org.jclouds.blobstore.domain.PageSet from) { return new BoundedLinkedHashSet(Iterables.transform(from, new Function() { public DirectoryEntry apply(StorageMetadata from) { FileType type = (from.getType() == StorageType.FOLDER || from.getType() == StorageType.RELATIVE_PATH) ? FileType.DIRECTORY : FileType.REGULAR; return new DirectoryEntry(from.getProviderId(), type, from.getName(), from.getSize()); } }), from.getNextMarker()); } } ================================================ FILE: apis/atmos/src/test/java/org/jclouds/atmos/blobstore/integration/AtmosBlobSignerLiveTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.blobstore.integration; import static org.testng.Assert.fail; import org.jclouds.blobstore.integration.internal.BaseBlobSignerLiveTest; import org.testng.SkipException; import org.testng.annotations.Test; @Test(groups = { "live" }) public class AtmosBlobSignerLiveTest extends BaseBlobSignerLiveTest { public AtmosBlobSignerLiveTest() { provider = "atmos"; } @Test public void testSignPutUrlWithTime() throws Exception { try { super.testSignPutUrlWithTime(); fail(); } catch (UnsupportedOperationException uoe) { throw new SkipException("not supported in Atmos", uoe); } } @Test public void testSignPutUrlWithTimeExpired() throws Exception { try { super.testSignPutUrlWithTimeExpired(); fail(); } catch (UnsupportedOperationException uoe) { throw new SkipException("not supported in Atmos", uoe); } } } ================================================ FILE: apis/atmos/src/test/java/org/jclouds/atmos/blobstore/integration/AtmosContainerIntegrationLiveTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.blobstore.integration; import org.jclouds.blobstore.integration.internal.BaseContainerIntegrationTest; import org.testng.annotations.Test; import org.testng.SkipException; @Test(groups = "live") public class AtmosContainerIntegrationLiveTest extends BaseContainerIntegrationTest { public AtmosContainerIntegrationLiveTest() { provider = "atmos"; } @Override public void testDelimiter() throws Exception { throw new SkipException("Atmos does not use key names for markers"); } @Override public void testListMarkerAfterLastKey() throws Exception { throw new SkipException("cannot specify arbitrary markers"); } @Override public void testListMarkerPrefix() throws Exception { throw new SkipException("cannot specify arbitrary markers"); } @Override public void testListContainerWithZeroMaxResults() throws Exception { throw new SkipException("Atmos requires a positive integer for max results"); } @Override public void testContainerListWithPrefix() { throw new SkipException("Atmos can only list prefix which matches an existing directory"); } @Override public void testDelimiterList() { throw new SkipException("Delimiter support is not yet implemented"); } } ================================================ FILE: apis/atmos/src/test/java/org/jclouds/atmos/blobstore/integration/AtmosContainerLiveTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.blobstore.integration; import org.jclouds.blobstore.integration.internal.BaseContainerLiveTest; import org.testng.annotations.Test; @Test(groups = { "live" }) public class AtmosContainerLiveTest extends BaseContainerLiveTest { public AtmosContainerLiveTest() { provider = "atmos"; } } ================================================ FILE: apis/atmos/src/test/java/org/jclouds/atmos/blobstore/integration/AtmosIntegrationLiveTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.blobstore.integration; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.failBecauseExceptionWasNotThrown; import java.io.IOException; import java.util.concurrent.ExecutionException; import org.jclouds.blobstore.BlobStore; import org.jclouds.blobstore.domain.Blob; import org.jclouds.blobstore.domain.BlobMetadata; import org.jclouds.blobstore.domain.StorageMetadata; import org.jclouds.blobstore.domain.Tier; import org.jclouds.blobstore.integration.internal.BaseBlobIntegrationTest; import org.jclouds.blobstore.options.ListContainerOptions; import org.testng.SkipException; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import com.google.common.io.ByteSource; @Test(groups = { "integration", "live" }) public class AtmosIntegrationLiveTest extends BaseBlobIntegrationTest { public AtmosIntegrationLiveTest() { provider = "atmos"; } @DataProvider(name = "delete") // no unicode support @Override public Object[][] createData() { return new Object[][] { { "normal" } }; } @Override public void testGetTwoRanges() { throw new SkipException("Atmos MIME-encodes multiple ranges"); } // not supported @Override protected void checkCacheControl(Blob blob, String cacheControl) { assertThat(blob.getPayload().getContentMetadata().getCacheControl()).isNull(); assertThat(blob.getMetadata().getContentMetadata().getCacheControl()).isNull(); } // not supported @Override protected void checkContentDisposition(Blob blob, String contentDisposition) { assert blob.getPayload().getContentMetadata().getContentDisposition() == null; assert blob.getMetadata().getContentMetadata().getContentDisposition() == null; } // not supported @Override protected void checkContentEncoding(Blob blob, String contentEncoding) { assert blob.getPayload().getContentMetadata().getContentEncoding() == null; assert blob.getMetadata().getContentMetadata().getContentEncoding() == null; } // not supported @Override protected void checkContentLanguage(Blob blob, String contentLanguage) { assert blob.getPayload().getContentMetadata().getContentLanguage() == null; assert blob.getMetadata().getContentMetadata().getContentLanguage() == null; } @Override @Test(expectedExceptions = IllegalArgumentException.class) public void testPutObjectStream() throws InterruptedException, IOException, ExecutionException { super.testPutObjectStream(); } @Override public void testCreateBlobWithExpiry() throws InterruptedException { throw new SkipException("Expiration not yet implemented"); } @Override public void testMultipartUploadNoPartsAbort() throws Exception { throw new SkipException("Atmos does not support multipart uploads"); } @Override public void testMultipartUploadSinglePart() throws Exception { throw new SkipException("Atmos does not support multipart uploads"); } @Override public void testMultipartUploadMultipleParts() throws Exception { throw new SkipException("Atmos does not support multipart uploads"); } @Override public void testListMultipartUploads() throws Exception { try { super.testListMultipartUploads(); } catch (UnsupportedOperationException uoe) { throw new SkipException("Atmos does not support multipart uploads", uoe); } } @Override public void testPutMultipartByteSource() throws Exception { throw new SkipException("Atmos does not support multipart uploads"); } @Override public void testPutMultipartInputStream() throws Exception { throw new SkipException("Atmos does not support multipart uploads"); } @Override @Test(groups = { "integration", "live" }, expectedExceptions = UnsupportedOperationException.class) public void testPutBlobAccessMultipart() throws Exception { super.testPutBlobAccessMultipart(); } @Override @Test(groups = { "integration", "live" }, expectedExceptions = UnsupportedOperationException.class) public void testCopyIfMatch() throws Exception { super.testCopyIfMatch(); } @Override @Test(groups = { "integration", "live" }, expectedExceptions = UnsupportedOperationException.class) public void testCopyIfMatchNegative() throws Exception { super.testCopyIfMatchNegative(); } @Override @Test(groups = { "integration", "live" }, expectedExceptions = UnsupportedOperationException.class) public void testCopyIfNoneMatch() throws Exception { super.testCopyIfNoneMatch(); } @Override @Test(groups = { "integration", "live" }, expectedExceptions = UnsupportedOperationException.class) public void testCopyIfNoneMatchNegative() throws Exception { super.testCopyIfNoneMatchNegative(); } @Test(groups = { "integration", "live" }) public void testPutBlobTierStandardMultipart() throws Exception { try { super.testPutBlobTierStandardMultipart(); failBecauseExceptionWasNotThrown(UnsupportedOperationException.class); } catch (UnsupportedOperationException uoe) { throw new SkipException("Atmos does not support multipart", uoe); } } @Test(groups = { "integration", "live" }) public void testPutBlobTierInfrequentMultipart() throws Exception { try { super.testPutBlobTierInfrequentMultipart(); failBecauseExceptionWasNotThrown(UnsupportedOperationException.class); } catch (UnsupportedOperationException uoe) { throw new SkipException("Atmos does not support multipart", uoe); } } @Test(groups = { "integration", "live" }) public void testPutBlobTierArchiveMultipart() throws Exception { try { super.testPutBlobTierArchiveMultipart(); failBecauseExceptionWasNotThrown(UnsupportedOperationException.class); } catch (UnsupportedOperationException uoe) { throw new SkipException("Atmos does not support multipart", uoe); } } @Override protected void checkTier(BlobMetadata metadata, Tier expected) { // Atmos maps all tiers to STANDARD assertThat(metadata.getTier()).isEqualTo(Tier.STANDARD); } // TODO: promote test to portable abstraction? @Test(groups = { "integration", "live" }) public void testETag() throws Exception { String blobName = "test-etag"; ByteSource payload = ByteSource.empty(); BlobStore blobStore = view.getBlobStore(); String containerName = getContainerName(); try { Blob blob = blobStore.blobBuilder(blobName) .payload(payload) .contentLength(payload.size()) .build(); String eTag = blobStore.putBlob(containerName, blob); assertThat(eTag).hasSize(44); BlobMetadata metadata = blobStore.blobMetadata(containerName, blobName); assertThat(metadata.getETag()).isEqualTo(eTag); for (StorageMetadata sm : blobStore.list(containerName, ListContainerOptions.NONE)) { assertThat(sm.getETag()).isEqualTo(eTag); } } finally { returnContainer(containerName); } } } ================================================ FILE: apis/atmos/src/test/java/org/jclouds/atmos/blobstore/integration/AtmosLiveTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.blobstore.integration; import org.jclouds.blobstore.integration.internal.BaseBlobLiveTest; import org.testng.annotations.Test; @Test(groups = { "live" }) public class AtmosLiveTest extends BaseBlobLiveTest { public AtmosLiveTest() { provider = "atmos"; } } ================================================ FILE: apis/atmos/src/test/java/org/jclouds/atmos/blobstore/integration/AtmosServiceIntegrationLiveTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.blobstore.integration; import org.jclouds.blobstore.integration.internal.BaseServiceIntegrationTest; import org.testng.annotations.Test; @Test(groups = "live") public class AtmosServiceIntegrationLiveTest extends BaseServiceIntegrationTest { public AtmosServiceIntegrationLiveTest() { provider = "atmos"; } } ================================================ FILE: apis/atmos/src/test/java/org/jclouds/atmos/fallbacks/EndpointIfAlreadyExistsTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.fallbacks; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNull; import java.net.URI; import org.jclouds.blobstore.KeyAlreadyExistsException; import org.testng.annotations.Test; @Test(groups = "unit") public class EndpointIfAlreadyExistsTest { @Test public void testFoundIsNullWhenEndpointNotSet() throws Exception { assertNull(new EndpointIfAlreadyExists().createOrPropagate(new KeyAlreadyExistsException())); } @Test public void testFoundIsEndpointWhenSet() throws Exception { assertEquals( new EndpointIfAlreadyExists().setEndpoint(URI.create("foo")).createOrPropagate( new KeyAlreadyExistsException()), URI.create("foo")); } @Test(expectedExceptions = RuntimeException.class) public void testNotFoundPropagates() throws Exception { new EndpointIfAlreadyExists().createOrPropagate(new RuntimeException()); } @Test(expectedExceptions = NullPointerException.class) public void testNullIsBad() throws Exception { new EndpointIfAlreadyExists().createOrPropagate(null); } } ================================================ FILE: apis/atmos/src/test/java/org/jclouds/atmos/filters/SignRequestTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.filters; import static org.testng.Assert.assertEquals; import java.io.IOException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import jakarta.ws.rs.core.MediaType; import org.jclouds.ContextBuilder; import org.jclouds.atmos.config.AtmosHttpApiModule; import org.jclouds.atmos.reference.AtmosHeaders; import org.jclouds.date.TimeStamp; import org.jclouds.http.HttpRequest; import org.jclouds.logging.config.NullLoggingModule; import org.jclouds.rest.ConfiguresHttpApi; import org.jclouds.rest.internal.BaseRestApiTest.MockModule; import org.jclouds.util.Strings2; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import com.google.common.base.Supplier; import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableMultimap.Builder; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Multimap; import com.google.common.net.HttpHeaders; import com.google.inject.Injector; import com.google.inject.Module; @Test(groups = "unit") public class SignRequestTest { private static final String EXPECTED_SIGNATURE = "WHJo1MFevMnK4jCthJ974L3YHoo="; private static final String UID = "6039ac182f194e15b9261d73ce044939/user1"; private static final String DEFAULT_DATE = "Thu, 05 Jun 2008 16:38:19 GMT"; private static final String KEY = "LJLuryj6zs8ste6Y3jTGQp71xq0="; private SignRequest filter; @Test void testCreateStringToSign() throws IOException { String expects = Strings2.toStringAndClose(getClass().getResourceAsStream("/hashstring.txt")); HttpRequest request = newRequest(preconstructedHeaders().build()); String toSign = filter.createStringToSign(request); assertEquals(toSign, expects); } @Test void testSignString() throws IOException, NoSuchAlgorithmException, InvalidKeyException { HttpRequest request = newRequest(preconstructedHeaders().build()); String toSign = filter.createStringToSign(request); String signature = filter.signString(toSign); assertEquals(signature, EXPECTED_SIGNATURE); } @Test void testFilter() throws IOException, NoSuchAlgorithmException, InvalidKeyException { HttpRequest request = newRequest(inputHeaders().build()); request = filter.filter(request); assertEquals(request.getFirstHeaderOrNull(AtmosHeaders.SIGNATURE), EXPECTED_SIGNATURE); } @Test void testFilterReplacesOldValues() throws IOException, NoSuchAlgorithmException, InvalidKeyException { HttpRequest request = newRequest(inputHeaders().put(AtmosHeaders.SIGNATURE, "foo") .put(HttpHeaders.DATE, "foo").put(AtmosHeaders.DATE, "foo").put(AtmosHeaders.UID, "foo") .build()); request = filter.filter(request); assertEquals(request.getFirstHeaderOrNull(AtmosHeaders.SIGNATURE), EXPECTED_SIGNATURE); } @BeforeClass protected void createFilter() { Injector injector = ContextBuilder .newBuilder("atmos") .credentials(UID, KEY) .modules( ImmutableSet. of(new MockModule(), new TestAtmosHttpApiModule(), new NullLoggingModule())) .buildInjector(); filter = injector.getInstance(SignRequest.class); } @ConfiguresHttpApi private static final class TestAtmosHttpApiModule extends AtmosHttpApiModule { @Override protected void configure() { super.configure(); } @Override protected String provideTimeStamp(@TimeStamp Supplier cache) { return DEFAULT_DATE; } } public HttpRequest newRequest(Multimap headers) { HttpRequest request = HttpRequest.builder() .method("POST") .endpoint("http://localhost/rest/objects") .headers(headers).build(); request.setPayload(""); request.getPayload().getContentMetadata().setContentLength(4286L); request.getPayload().getContentMetadata().setContentType(MediaType.APPLICATION_OCTET_STREAM); return request; } protected Builder preconstructedHeaders() { Builder builder = inputHeaders(); builder.put(HttpHeaders.DATE, DEFAULT_DATE); builder.put(AtmosHeaders.UID, UID); return builder; } protected Builder inputHeaders() { Builder builder = ImmutableMultimap.builder(); builder.put(AtmosHeaders.LISTABLE_META, "part4/part7/part8=quick"); builder.put(AtmosHeaders.META, "part1=buy"); builder.put(HttpHeaders.ACCEPT, "*/*"); builder.put(AtmosHeaders.USER_ACL, "john=FULL_CONTROL,mary=WRITE"); builder.put(AtmosHeaders.GROUP_ACL, "other=NONE"); builder.put(AtmosHeaders.DATE, DEFAULT_DATE); builder.put(HttpHeaders.HOST, "10.5.115.118"); return builder; } } ================================================ FILE: apis/atmos/src/test/java/org/jclouds/atmos/functions/AtmosObjectNameTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.functions; import static org.testng.Assert.assertEquals; import java.io.File; import org.jclouds.atmos.domain.AtmosObject; import org.jclouds.atmos.domain.SystemMetadata; import org.jclouds.atmos.domain.UserMetadata; import org.jclouds.atmos.domain.AtmosObject.Factory; import org.testng.annotations.Test; import com.google.inject.Guice; @Test(groups = "unit") public class AtmosObjectNameTest { AtmosObjectName fn = new AtmosObjectName(); private static final Factory BLOB_FACTORY = Guice.createInjector().getInstance(AtmosObject.Factory.class); @Test public void testCorrectContentMetadataName() throws SecurityException, NoSuchMethodException { AtmosObject blob = BLOB_FACTORY.create(null); blob.getContentMetadata().setName("foo"); assertEquals(fn.apply(blob), "foo"); } @Test public void testCorrectSystemMetadataObjectName() throws SecurityException, NoSuchMethodException { AtmosObject blob = BLOB_FACTORY.create(new SystemMetadata(null, null, null, null, null, null, 0, null, "foo", null, 0, null, null), new UserMetadata()); assertEquals(fn.apply(blob), "foo"); } @Test(expectedExceptions = IllegalArgumentException.class) public void testMustBeAtmosObject() { fn.apply(new File("foo")); } @Test(expectedExceptions = { NullPointerException.class, IllegalStateException.class }) public void testNullIsBad() { fn.apply(null); } } ================================================ FILE: apis/atmos/src/test/java/org/jclouds/atmos/functions/ParseDirectoryListFromContentAndHeadersTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.functions; import static org.testng.Assert.assertEquals; import java.util.Set; import org.jclouds.atmos.domain.BoundedSet; import org.jclouds.atmos.domain.DirectoryEntry; import org.jclouds.atmos.domain.FileType; import org.jclouds.atmos.domain.internal.BoundedLinkedHashSet; import org.jclouds.atmos.reference.AtmosHeaders; import org.jclouds.http.HttpResponse; import org.jclouds.http.functions.BaseHandlerTest; import org.jclouds.io.Payloads; import org.testng.annotations.Test; import com.google.common.base.Function; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet.Builder; /** * Tests behavior of {@code ParseDirectoryListFromContentAndHeaders} */ //NOTE:without testName, this will not call @Before* and fail w/NPE during surefire @Test(groups = "unit", testName = "ParseDirectoryListFromContentAndHeadersTest") public class ParseDirectoryListFromContentAndHeadersTest extends BaseHandlerTest { Function> createFn() { return injector.getInstance(ParseDirectoryListFromContentAndHeaders.class); } public void testWithToken() { HttpResponse response = HttpResponse.builder() .statusCode(200) .message("ok") .payload(Payloads.newPayload(getClass().getResourceAsStream("/list_basic.xml"))) .addHeader(AtmosHeaders.TOKEN, "token").build(); BoundedSet result = createFn().apply(response); assertEquals(result, new BoundedLinkedHashSet(values(), "token")); assertEquals(result.getToken(), "token"); } public void testWithoutToken() { HttpResponse response = HttpResponse.builder() .statusCode(200) .message("ok") .payload(Payloads.newPayload(getClass().getResourceAsStream("/list_basic.xml"))).build(); BoundedSet result = createFn().apply(response); assertEquals(ImmutableSet.copyOf(result), values()); assertEquals(result.getToken(), null); } protected Set values() { Builder expected = ImmutableSet.builder(); expected.add(new DirectoryEntry("4980cdb2a411106a04a4538c92a1b204ad92077de6e3", FileType.DIRECTORY, "adriancole-blobstore-2096685753", 0)); expected.add(new DirectoryEntry("4980cdb2a410105404980d99e53a0504ad93939e7dc3", FileType.DIRECTORY, "adriancole-blobstore247496608", 0)); return expected.build(); } } ================================================ FILE: apis/atmos/src/test/java/org/jclouds/atmos/functions/ParseObjectFromHeadersAndHttpContentTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.functions; import static org.testng.Assert.assertEquals; import org.jclouds.atmos.domain.AtmosObject; import org.jclouds.atmos.reference.AtmosHeaders; import org.jclouds.http.HttpResponse; import org.testng.annotations.Test; import com.google.common.collect.ImmutableMultimap; import com.google.inject.Guice; /** * Tests behavior of {@code ParseObjectFromHeadersAndHttpContent} */ @Test(groups = "unit", testName = "ParseObjectFromHeadersAndHttpContentTest") public class ParseObjectFromHeadersAndHttpContentTest { static final HttpResponse RESPONSE = HttpResponse.builder() .statusCode(200) .message("ok") .payload("") .headers( ImmutableMultimap.of(AtmosHeaders.TAGS, "tag1, tag2", AtmosHeaders.LISTABLE_TAGS, "listabletag1, listabletag2", AtmosHeaders.META, "meta1=foo1, content-md5=1f3870be274f6c49b3e31a0c6728957f, atime=2009-10-12T16:09:42Z, mtime=2009-10-19T04:37:00Z," + " ctime=2009-10-19T04:37:00Z, itime=2009-10-12T16:09:42Z, type=directory, uid=root, " + "gid=rootr, objectid=4980cdb2b010109b04a44f7bb83f5f04ad354c638ae5, " + "objname=e913e09366364e9ba384b8fead643d43, size=4096, nlink=1, policyname=default", AtmosHeaders.LISTABLE_META, "listablemeta1=listablefoo1, listablemeta2=listablefoo2")).build(); public static final AtmosObject EXPECTED; static { EXPECTED = Guice.createInjector().getInstance(AtmosObject.Factory.class) .create(ParseSystemMetadataFromHeadersTest.EXPECTED, ParseUserMetadataFromHeadersTest.EXPECTED); EXPECTED.getContentMetadata().setName("e913e09366364e9ba384b8fead643d43"); EXPECTED.setPayload(RESPONSE.getPayload()); } public void test() { ParseObjectFromHeadersAndHttpContent parser = Guice.createInjector().getInstance( ParseObjectFromHeadersAndHttpContent.class); AtmosObject data = parser.apply(RESPONSE); assertEquals(data, EXPECTED); } } ================================================ FILE: apis/atmos/src/test/java/org/jclouds/atmos/functions/ParseSystemMetadataFromHeadersTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.functions; import static com.google.common.io.BaseEncoding.base16; import static org.testng.Assert.assertEquals; import org.jclouds.atmos.domain.FileType; import org.jclouds.atmos.domain.SystemMetadata; import org.jclouds.date.DateService; import org.jclouds.date.internal.SimpleDateFormatDateService; import org.testng.annotations.Test; import com.google.inject.Guice; /** * Tests behavior of {@code ParseSystemMetadataFromHeaders} */ @Test(groups = "unit") public class ParseSystemMetadataFromHeadersTest { static final DateService dateService = new SimpleDateFormatDateService(); static final SystemMetadata EXPECTED = new SystemMetadata(base16().lowerCase().decode("1f3870be274f6c49b3e31a0c6728957f"), dateService.iso8601SecondsDateParse("2009-10-12T16:09:42Z"), dateService.iso8601SecondsDateParse("2009-10-19T04:37:00Z"), "rootr", dateService.iso8601SecondsDateParse("2009-10-12T16:09:42Z"), dateService.iso8601SecondsDateParse("2009-10-19T04:37:00Z"), 1, "4980cdb2b010109b04a44f7bb83f5f04ad354c638ae5", "e913e09366364e9ba384b8fead643d43", "default", 4096L, FileType.DIRECTORY, "root" ); public void test() { ParseSystemMetadataFromHeaders parser = Guice.createInjector().getInstance(ParseSystemMetadataFromHeaders.class); SystemMetadata data = parser.apply(ParseObjectFromHeadersAndHttpContentTest.RESPONSE); assertEquals(data, EXPECTED); } } ================================================ FILE: apis/atmos/src/test/java/org/jclouds/atmos/functions/ParseUserMetadataFromHeadersTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.functions; import static org.testng.Assert.assertEquals; import org.jclouds.atmos.domain.UserMetadata; import org.testng.annotations.Test; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.inject.Guice; /** * Tests behavior of {@code ParseUserMetadataFromHeaders} */ @Test(groups = "unit") public class ParseUserMetadataFromHeadersTest { static final UserMetadata EXPECTED = new UserMetadata(ImmutableMap. of("meta1", "foo1"), ImmutableMap.of("listablemeta1", "listablefoo1", "listablemeta2", "listablefoo2"), ImmutableSet.of("tag1", "tag2"), ImmutableSet.of("listabletag1", "listabletag2")); public void test() { ParseUserMetadataFromHeaders parser = Guice.createInjector().getInstance(ParseUserMetadataFromHeaders.class); UserMetadata data = parser.apply(ParseObjectFromHeadersAndHttpContentTest.RESPONSE); assertEquals(data, EXPECTED); } } ================================================ FILE: apis/atmos/src/test/java/org/jclouds/atmos/handlers/AtmosServerErrorRetryHandlerTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.handlers; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import org.jclouds.atmos.domain.AtmosError; import org.jclouds.atmos.util.AtmosUtils; import org.jclouds.http.handlers.BackoffLimitedRetryHandler; import org.jclouds.http.HttpCommand; import org.jclouds.http.HttpResponse; import org.testng.annotations.Test; /** * Tests behavior of {@code AtmosServerErrorRetryHandler} */ @Test(groups = "unit") public class AtmosServerErrorRetryHandlerTest { private static final String HTTP_MESSAGE_FORMAT = "\n" + "\n" + "%d\n" + "%s\n" + "\n"; @Test public void testGet500WithoutError() { AtmosUtils utils = createMock(AtmosUtils.class); BackoffLimitedRetryHandler backoffLimitedRetryHandler = createMock(BackoffLimitedRetryHandler.class); HttpCommand command = createMock(HttpCommand.class); expect(command.getFailureCount()).andReturn(0).once(); expect(command.incrementFailureCount()).andReturn(1).once(); replay(utils, backoffLimitedRetryHandler, command); AtmosServerErrorRetryHandler retry = new AtmosServerErrorRetryHandler(backoffLimitedRetryHandler, utils); assertFalse(retry.shouldRetryRequest(command, HttpResponse.builder().statusCode(500).build())); verify(utils, backoffLimitedRetryHandler, command); } @Test public void testGet500WithError1040() { AtmosUtils utils = createMock(AtmosUtils.class); BackoffLimitedRetryHandler backoffLimitedRetryHandler = createMock(BackoffLimitedRetryHandler.class); HttpCommand command = createMock(HttpCommand.class); String content = String.format(HTTP_MESSAGE_FORMAT, 1040, "The server is busy. Please try again"); HttpResponse response = HttpResponse.builder().statusCode(500).payload(content).build(); expect(command.getFailureCount()).andReturn(0).once(); expect(utils.parseAtmosErrorFromContent(command, response, content)).andReturn(new AtmosError(1040, "The server is busy. Please try again")).once(); expect(backoffLimitedRetryHandler.shouldRetryRequest(command, response)).andReturn(true).once(); replay(utils, backoffLimitedRetryHandler, command); AtmosServerErrorRetryHandler retry = new AtmosServerErrorRetryHandler(backoffLimitedRetryHandler, utils); assertTrue(retry.shouldRetryRequest(command, response)); verify(utils, backoffLimitedRetryHandler, command); } } ================================================ FILE: apis/atmos/src/test/java/org/jclouds/atmos/options/ListOptionsTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.options; import static org.testng.Assert.assertEquals; import org.testng.annotations.Test; import com.google.common.collect.ImmutableList; /** * Tests behavior of {@code ListOptions} */ @Test(groups = "unit") public class ListOptionsTest { public void testToken() { ListOptions options = new ListOptions().token("a"); assertEquals(ImmutableList.of("a"), options.buildRequestHeaders().get("x-emc-token")); } public void testTokenStatic() { ListOptions options = ListOptions.Builder.token("a"); assertEquals(ImmutableList.of("a"), options.buildRequestHeaders().get("x-emc-token")); } public void testLimit() { int limit = 1; ListOptions options = new ListOptions().limit(limit); assertEquals(ImmutableList.of("1"), options.buildRequestHeaders().get("x-emc-limit")); } public void testLimitStatic() { int limit = 1; ListOptions options = ListOptions.Builder.limit(limit); assertEquals(ImmutableList.of("1"), options.buildRequestHeaders().get("x-emc-limit")); } public void testNoMeta() { ListOptions options = new ListOptions(); assert !options.metaIncluded(); } public void testMeta() { ListOptions options = new ListOptions().includeMeta(); assertEquals(ImmutableList.of("1"), options.buildRequestHeaders().get("x-emc-include-meta")); assert options.metaIncluded(); } public void testMetaStatic() { ListOptions options = ListOptions.Builder.includeMeta(); assertEquals(ImmutableList.of("1"), options.buildRequestHeaders().get("x-emc-include-meta")); assert options.metaIncluded(); } } ================================================ FILE: apis/atmos/src/test/java/org/jclouds/atmos/xml/ErrorHandlerTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.xml; import static org.testng.Assert.assertEquals; import java.io.InputStream; import org.jclouds.atmos.domain.AtmosError; import org.jclouds.atmos.reference.AtmosErrorCode; import org.jclouds.http.functions.BaseHandlerTest; import org.jclouds.http.functions.ParseSax; import org.testng.annotations.Test; /** * Tests behavior of {@code ErrorHandler} */ // NOTE:without testName, this will not call @Before* and fail w/NPE during surefire @Test(groups = "unit", testName = "ErrorHandlerTest") public class ErrorHandlerTest extends BaseHandlerTest { ParseSax createParser() { ParseSax parser = factory.create(injector .getInstance(ErrorHandler.class)); return parser; } public void testApplyInputStream() { InputStream is = getClass().getResourceAsStream("/error.xml"); ParseSax parser = createParser(); AtmosError result = parser.parse(is); assertEquals(result.getCode(), AtmosErrorCode.OBJECT_NOT_FOUND.getCode()); } } ================================================ FILE: apis/atmos/src/test/java/org/jclouds/atmos/xml/ListDirectoryResponseHandlerTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.atmos.xml; import static org.testng.Assert.assertEquals; import java.io.InputStream; import java.util.Set; import org.jclouds.atmos.domain.DirectoryEntry; import org.jclouds.atmos.domain.FileType; import org.jclouds.http.functions.BaseHandlerTest; import org.jclouds.http.functions.ParseSax; import org.testng.annotations.Test; import com.google.common.collect.Sets; /** * Tests behavior of {@code ListDirectoryResponseHandler} */ //NOTE:without testName, this will not call @Before* and fail w/NPE during surefire @Test(groups = "unit", testName = "ListDirectoryResponseHandlerTest") public class ListDirectoryResponseHandlerTest extends BaseHandlerTest { ParseSax> createParser() { ParseSax> parser = factory .create(injector.getInstance(ListDirectoryResponseHandler.class)); return parser; } public void testApplyInputStreamBase() { InputStream is = getClass().getResourceAsStream("/list_basic.xml"); ParseSax> parser = createParser(); Set expected = Sets.newTreeSet(); expected.add(new DirectoryEntry("4980cdb2a411106a04a4538c92a1b204ad92077de6e3", FileType.DIRECTORY, "adriancole-blobstore-2096685753", 0)); expected.add(new DirectoryEntry("4980cdb2a410105404980d99e53a0504ad93939e7dc3", FileType.DIRECTORY, "adriancole-blobstore247496608", 0)); Set result = parser.parse(is); assertEquals(result, expected); } } ================================================ FILE: apis/atmos/src/test/resources/error.xml ================================================ 1003 The requested object was not found. ================================================ FILE: apis/atmos/src/test/resources/hashstring.txt ================================================ POST application/octet-stream Thu, 05 Jun 2008 16:38:19 GMT /rest/objects x-emc-date:Thu, 05 Jun 2008 16:38:19 GMT x-emc-groupacl:other=NONE x-emc-listable-meta:part4/part7/part8=quick x-emc-meta:part1=buy x-emc-uid:6039ac182f194e15b9261d73ce044939/user1 x-emc-useracl:john=FULL_CONTROL,mary=WRITE ================================================ FILE: apis/atmos/src/test/resources/list_basic.xml ================================================ 4980cdb2a411106a04a4538c92a1b204ad92077de6e3 directory adriancole-blobstore-2096685753 4980cdb2a410105404980d99e53a0504ad93939e7dc3 directory adriancole-blobstore247496608 ================================================ FILE: apis/atmos/src/test/resources/list_meta.xml ================================================ 499ad542a2a8bc200499ad5a7099940499b44f51e97d atime 2009-02-17T23:15:01Z mtime 2009-02-17T23:15:01Z ctime 2009-02-17T23:15:01Z itime 2009-02-17T23:15:01Z type regular uid user1 gid apache objectid 499ad542a2a8bc200499ad5a7099940499b44f51e97d objname size 7589 nlink 0 policyname default part1 order false part4/part7/part8 quick true ================================================ FILE: apis/atmos/src/test/resources/log4j.xml ================================================ ================================================ FILE: apis/byon/README.txt ================================================ = Bring Your Own Nodes to the jclouds ComputeService = The bring your own node provider (byon) allows you to specify a source which jclouds will read nodes from. Using this, you can have jclouds control your standalone machines, or even cloud hosts that are sitting idle. == Constraints == The byon provider only supports the following functions of ComputeService: * listNodes * listNodesDetailsMatching * getNodeMetadata * runScriptOnNodesMatching == How to use the byon provider == The byon provider requires you supply a list of nodes using a property. Here are the valid properties you can use: * byon.endpoint - url to access the list, can be http://, file://, classpath:// * byon.nodes - inline defined yaml in string form. Note: The identity and credential fields of the ComputeServiceContextFactory are ignored. === Java example === Properties props = new Properties(); // if you built the yaml string by hand props.setProperty("byon.nodes", stringLiteral); // or you can specify an external reference props.setProperty("byon.endpoint", "file://path/to/byon.yaml"); // or you can specify a file in your classpath props.setProperty("byon.endpoint", "classpath:///byon.yaml"); context = new ComputeServiceContextFactory().createContext("byon", "foo", "bar", ImmutableSet. of(new JschSshClientModule()), props); == File format == You must define your nodes in yaml, and they must be in a collection called nodes. Here are the properties: * id - opaque unique id * name - optional; user specified name * description - optional; long description of this node * note this is not yet in jclouds NodeMetadata * hostname - name or ip address to contact the node on * location_id - optional; correlates to a ZONE-scoped Location * note that if present for one node, must be present for all * os_arch - ex. x86 * os_family - must conform to org.jclouds.compute.domain.OsFamily in lower-hyphen format ex. rhel, ubuntu, centos, debian, amzn-linux * os_description - long description of the os ex. Ubuntu with lamp stack * os_version - normalized to numbers when possible. ex. for centos: 5.3, ubuntu: 10.10 * login_port - optional; alternate port for ssh access * group - primary group of the machine. ex. hadoop * tags - optional; list of arbitrary tags. * note this list is not yet in jclouds NodeMetadata * username - primary login user. ex. ubuntu, toor, root * sudo_password - optional; when a script is run with the "runAsRoot" option true, yet the username is not root, a sudo command is invoked. If sudo_password is set, the contents will be passed to sudo -S. Ex. echo 'foobar'| sudo -S init 5 one of: * credential - RSA private key or password * credential_url - location of plain-text RSA private key or password. ex. file:///home/me/.ssh/id_rsa classpath:///id_rsa Note that username and credentials are optional if a CredentialStoreModule is configured in jclouds. === Example File === nodes: - id: i-sdfkjh7 name: cluster-1 description: accounting analytics cluster hostname: cluster-1.mydomain.com location_id: virginia os_arch: x86 os_family: rhel os_description: redhat with CDH os_version: 5.3 group: hadoop tags: - vanilla username: myUser credential: | -----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEAuzaE6azgUxwESX1rCGdJ5xpdrc1XC311bOGZBCE8NA+CpFh2 u01Vfv68NC4u6LFgdXSY1vQt6hiA5TNqQk0TyVfFAunbXgTekF6XqDPQUf1nq9aZ lMvo4vlaLDKBkhG5HJE/pIa0iB+RMZLS0GhxsIWerEDmYdHKM25o -----END RSA PRIVATE KEY----- sudo_password: go panthers! ================================================ FILE: apis/byon/bnd.bnd ================================================ Export-Package: \ org.jclouds.byon.*;version="${project.version}";-noimport:=true ================================================ FILE: apis/byon/pom.xml ================================================ 4.0.0 org.apache.jclouds jclouds-project 2.7.1-SNAPSHOT ../../project/pom.xml org.apache.jclouds.api byon jclouds bring your own node provider file://c:/test.txt org.apache.jclouds jclouds-core ${project.version} test-jar test org.apache.jclouds jclouds-compute ${project.version} org.apache.jclouds jclouds-compute ${project.version} test-jar test org.apache.jclouds.driver jclouds-log4j ${project.version} test org.apache.jclouds.driver jclouds-sshj ${project.version} test org.yaml snakeyaml 2.3 com.google.auto.service auto-service true live org.apache.maven.plugins maven-surefire-plugin integration integration-test test ${test.byon.endpoint} ${test.byon.sudo-password} ================================================ FILE: apis/byon/src/main/java/org/jclouds/byon/BYONApiMetadata.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.byon; import java.net.URI; import org.jclouds.JcloudsVersion; import org.jclouds.apis.ApiMetadata; import org.jclouds.apis.internal.BaseApiMetadata; import org.jclouds.byon.config.BYONComputeServiceContextModule; import org.jclouds.byon.config.YamlNodeStoreModule; import org.jclouds.compute.ComputeServiceContext; import com.google.auto.service.AutoService; import com.google.common.collect.ImmutableSet; import com.google.inject.Module; /** * Implementation of {@link ApiMetadata} for jclouds BYON API * *

note

* * This class is not setup to allow a subclasses to override the type of api, * asyncapi, or context. This is an optimization for s. */ @AutoService(ApiMetadata.class) public class BYONApiMetadata extends BaseApiMetadata { @Override public Builder toBuilder() { return new Builder().fromApiMetadata(this); } public BYONApiMetadata() { this(new Builder()); } protected BYONApiMetadata(Builder builder) { super(builder); } public static class Builder extends BaseApiMetadata.Builder { protected Builder() { id("byon") .name("Bring Your Own Node (BYON) API") .identityName("Unused") .defaultIdentity("foo") .defaultCredential("bar") .defaultEndpoint("file://byon.yaml") .documentation(URI.create("https://github.com/jclouds/jclouds/tree/master/apis/byon")) .version(String.format("%s.%s", JcloudsVersion.get().majorVersion, JcloudsVersion.get().minorVersion)) .buildVersion(JcloudsVersion.get().toString()) .view(ComputeServiceContext.class) .defaultModules(ImmutableSet.>of(YamlNodeStoreModule.class, BYONComputeServiceContextModule.class)); } @Override public BYONApiMetadata build() { return new BYONApiMetadata(this); } @Override protected Builder self() { return this; } } } ================================================ FILE: apis/byon/src/main/java/org/jclouds/byon/Node.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.byon; import java.net.URI; import java.util.Map; import java.util.Set; import com.google.common.base.MoreObjects; import com.google.common.base.Objects; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; import com.google.common.collect.Sets; public class Node { public static Builder builder() { return new Builder(); } public static class Builder { private String id; private String name; private String description; private String hostname; private String locationId; private String osArch; private String osFamily; private String osDescription; private String osVersion; private boolean os64Bit; private int loginPort = 22; private String group; private Set tags = ImmutableSet.of(); private Map metadata = ImmutableMap.of(); private String username; private String credential; private URI credentialUrl; private String sudoPassword; public Builder id(String id) { this.id = id; return this; } public Builder name(String name) { this.name = name; return this; } public Builder description(String description) { this.description = description; return this; } public Builder hostname(String hostname) { this.hostname = hostname; return this; } public Builder loginPort(int loginPort) { this.loginPort = loginPort; return this; } public Builder locationId(String locationId) { this.locationId = locationId; return this; } public Builder osArch(String osArch) { this.osArch = osArch; return this; } public Builder osFamily(String osFamily) { this.osFamily = osFamily; return this; } public Builder osDescription(String osDescription) { this.osDescription = osDescription; return this; } public Builder osVersion(String osVersion) { this.osVersion = osVersion; return this; } public Builder os64Bit(boolean os64Bit) { this.os64Bit = os64Bit; return this; } public Builder group(String group) { this.group = group; return this; } public Builder tags(Iterable tags) { this.tags = ImmutableSet.copyOf(tags); return this; } public Builder metadata(Map metadata) { this.metadata = ImmutableMap.copyOf(metadata); return this; } public Builder username(String username) { this.username = username; return this; } public Builder credential(String credential) { this.credential = credential; return this; } public Builder credentialUrl(URI credentialUrl) { this.credentialUrl = credentialUrl; return this; } public Builder sudoPassword(String sudoPassword) { this.sudoPassword = sudoPassword; return this; } public Node build() { return new Node(id, name, description, hostname, locationId, osArch, osFamily, osDescription, osVersion, os64Bit, loginPort, group, tags, metadata, username, credential, credentialUrl, sudoPassword); } } public Node(String id, String name, String description, String hostname, String locationId, String osArch, String osFamily, String osDescription, String osVersion, boolean os64Bit, int loginPort, String group, Iterable tags, Map metadata, String username, String credential, URI credentialUrl, String sudoPassword) { this.id = id; this.name = name; this.description = description; this.hostname = hostname; this.locationId = locationId; this.osArch = osArch; this.osFamily = osFamily; this.osDescription = osDescription; this.osVersion = osVersion; this.os64Bit = os64Bit; this.loginPort = loginPort; this.group = group; this.tags = ImmutableSet.copyOf(tags); this.metadata = ImmutableMap.copyOf(metadata); this.username = username; this.credential = credential; this.credentialUrl = credentialUrl; this.sudoPassword = sudoPassword; } private final String id; private final String name; private final String description; private final String hostname; private final String locationId; private final String osArch; private final String osFamily; private final String osDescription; private final String osVersion; private final int loginPort; private final boolean os64Bit; private final String group; private final Set tags; private final Map metadata; private final String username; private final String credential; private final URI credentialUrl; private final String sudoPassword; public String getId() { return id; } public String getLocationId() { return locationId; } public String getName() { return name; } public String getDescription() { return description; } public String getGroup() { return group; } public String getHostname() { return hostname; } public String getOsArch() { return osArch; } public String getOsFamily() { return osFamily; } public String getOsDescription() { return osDescription; } public String getOsVersion() { return osVersion; } public boolean isOs64Bit() { return os64Bit; } public int getLoginPort() { return loginPort; } public Set getTags() { Set tagSet = Sets.newHashSet(); for (String tag : tags) tagSet.add(tag); return tagSet; } public Map getMetadata() { return Maps.newLinkedHashMap(this.metadata); } public String getUsername() { return username; } public String getCredential() { return credential; } public URI getCredentialUrl() { return credentialUrl; } public String getSudoPassword() { return sudoPassword; } @Override public int hashCode() { return Objects.hashCode(id); } @Override public boolean equals(Object obj) { if (obj == null) return false; if (!(obj instanceof Node)) { return false; } Node that = (Node) obj; return Objects.equal(this.id, that.id) && Objects.equal(this.name, that.name) && Objects.equal(this.description, that.description) && Objects.equal(this.hostname, that.hostname) && Objects.equal(this.locationId, that.locationId) && Objects.equal(this.osArch, that.osArch) && Objects.equal(this.osFamily, that.osFamily) && Objects.equal(this.osDescription, that.osDescription) && Objects.equal(this.osVersion, that.osVersion) && Objects.equal(this.loginPort, that.loginPort) && Objects.equal(this.os64Bit, that.os64Bit) && Objects.equal(this.group, that.group) && Objects.equal(this.tags, that.tags) && Objects.equal(this.metadata, that.metadata) && Objects.equal(this.username, that.username) // not comparing credential and credentialUrl && Objects.equal(this.sudoPassword, that.sudoPassword); } @Override public String toString() { return MoreObjects.toStringHelper(this).add("id", id).add("name", name).add("description", description) .add("locationId", locationId).add("hostname", hostname).add("osArch", osArch).add("osFamily", osFamily) .add("osDescription", osDescription).add("osVersion", osVersion).add("os64Bit", os64Bit) .add("group", group).add("loginPort", loginPort).add("tags", tags).add("metadata", metadata) .add("username", username).add("hasCredential", credential != null || credentialUrl != null) .add("hasSudoPassword", sudoPassword != null).toString(); } } ================================================ FILE: apis/byon/src/main/java/org/jclouds/byon/config/BYONComputeServiceContextModule.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.byon.config; import java.io.InputStream; import java.net.URI; import org.jclouds.byon.internal.BYONComputeServiceAdapter; import org.jclouds.byon.suppliers.SupplyFromProviderURIOrNodesProperty; import org.jclouds.compute.config.JCloudsNativeComputeServiceAdapterContextModule; import org.jclouds.compute.domain.Hardware; import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.concurrent.SingleThreaded; import org.jclouds.domain.Location; import org.jclouds.location.Provider; import com.google.common.base.Function; import com.google.common.io.ByteSource; import com.google.inject.TypeLiteral; @SingleThreaded public class BYONComputeServiceContextModule extends JCloudsNativeComputeServiceAdapterContextModule { public BYONComputeServiceContextModule() { super(BYONComputeServiceAdapter.class); } @Override protected void configure() { super.configure(); bind(new TypeLiteral>() { }).to(SupplyFromProviderURIOrNodesProperty.class); bind(ByteSource.class).annotatedWith(Provider.class).to(SupplyFromProviderURIOrNodesProperty.class); bind(new TypeLiteral>() { }).to(SupplyFromProviderURIOrNodesProperty.class); install(new LocationsFromComputeServiceAdapterModule() { }); } } ================================================ FILE: apis/byon/src/main/java/org/jclouds/byon/config/CacheNodeStoreModule.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.byon.config; import static com.google.common.base.Preconditions.checkNotNull; import java.util.Map; import org.jclouds.byon.Node; import com.google.common.annotations.Beta; import com.google.common.base.Functions; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.inject.AbstractModule; import com.google.inject.TypeLiteral; @ConfiguresNodeStore @Beta public class CacheNodeStoreModule extends AbstractModule { private final LoadingCache backing; public CacheNodeStoreModule(LoadingCache backing) { this.backing = checkNotNull(backing, "backing"); } public CacheNodeStoreModule(Map backing) { this(CacheBuilder.newBuilder().build(CacheLoader.from(Functions.forMap(backing)))); for (String node : backing.keySet()) this.backing.getUnchecked(node); } @Override protected void configure() { bind(new TypeLiteral>() { }).toInstance(backing); bind(new TypeLiteral>>() { }).toInstance(Suppliers.> ofInstance(backing)); } } ================================================ FILE: apis/byon/src/main/java/org/jclouds/byon/config/ConfiguresNodeStore.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.byon.config; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Retention; import java.lang.annotation.Target; import com.google.common.annotations.Beta; /** * designates the module configures a {@code LoadingCache} */ @Beta @Retention(RUNTIME) @Target(TYPE) public @interface ConfiguresNodeStore { } ================================================ FILE: apis/byon/src/main/java/org/jclouds/byon/config/YamlNodeStoreModule.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.byon.config; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import jakarta.inject.Named; import jakarta.inject.Singleton; import org.jclouds.byon.Node; import org.jclouds.byon.domain.YamlNode; import org.jclouds.byon.functions.NodesFromYamlStream; import org.jclouds.byon.suppliers.NodesParsedFromSupplier; import org.jclouds.collect.TransformingMap; import com.google.common.annotations.Beta; import com.google.common.base.Function; import com.google.common.base.Functions; import com.google.common.base.Supplier; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.io.ByteSource; import com.google.inject.AbstractModule; import com.google.inject.Provides; import com.google.inject.TypeLiteral; import com.google.inject.name.Names; @ConfiguresNodeStore @Beta public class YamlNodeStoreModule extends AbstractModule { private static final Map BACKING = new ConcurrentHashMap(); private final Map backing; public YamlNodeStoreModule(Map backing) { this.backing = backing; } public YamlNodeStoreModule() { this(null); } @Override protected void configure() { bind(new TypeLiteral>>() { }).to(NodesParsedFromSupplier.class); bind(new TypeLiteral>>() { }).to(NodesFromYamlStream.class); bind(new TypeLiteral>() { }).toInstance(org.jclouds.byon.domain.YamlNode.yamlNodeToByteSource); bind(new TypeLiteral>() { }).toInstance(org.jclouds.byon.domain.YamlNode.byteSourceToYamlNode); bind(new TypeLiteral>() { }).toInstance(org.jclouds.byon.domain.YamlNode.nodeToYamlNode); bind(new TypeLiteral>() { }).toInstance(org.jclouds.byon.domain.YamlNode.toNode); if (backing != null) { bind(new TypeLiteral>() { }).annotatedWith(Names.named("yaml")).toInstance(backing); } else { bind(new TypeLiteral>() { }).annotatedWith(Names.named("yaml")).toInstance(BACKING); } } @Provides @Singleton protected final LoadingCache provideNodeStore(Map backing, Function yamlSerializer, Function yamlDeserializer) { return CacheBuilder.newBuilder().build(CacheLoader.from(Functions.forMap(new TransformingMap(backing, yamlDeserializer, yamlSerializer)))); } @Provides @Singleton protected final Map provideYamlStore(@Named("yaml") Map backing, Function yamlSerializer, Function yamlDeserializer) { return new TransformingMap(backing, yamlDeserializer, yamlSerializer); } } ================================================ FILE: apis/byon/src/main/java/org/jclouds/byon/domain/YamlNode.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.byon.domain; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.util.List; import java.util.Map; import org.jclouds.byon.Node; import org.jclouds.util.Closeables2; import org.yaml.snakeyaml.DumperOptions; import org.yaml.snakeyaml.LoaderOptions; import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.constructor.Constructor; import com.google.common.base.Charsets; import com.google.common.base.Function; import com.google.common.base.Throwables; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.ImmutableMap.Builder; import com.google.common.io.ByteSource; /** * Serializes to the following * *
 *       id: cluster-1
 *       name: cluster-1
 *       description: xyz
 *       hostname: cluster-1.mydomain.com
 *       location_id: virginia
 *       os_arch: x86
 *       os_family: linux
 *       os_description: redhat
 *       os_version: 5.3
 *       os_64bit: 5.3
 *       login_port: 2022
 *       group: hadoop
 *       tags:
 *           - vanilla
 *       metadata:
 *           key1: val1
 *       username: kelvin
 *       credential: password_or_rsa
 *         or
 *       credential_url: password_or_rsa_file ex. resource:///id_rsa will get the classpath /id_rsa; file://path/to/id_rsa
 *       sudo_password: password
 * 
*/ public class YamlNode { public String id; public String name; public String description; public String hostname; public String location_id; public String os_arch; public String os_family; public String os_description; public String os_version; public int login_port = 22; public boolean os_64bit; public String group; public List tags = Lists.newArrayList(); public Map metadata = Maps.newLinkedHashMap(); public String username; public String credential; public String credential_url; public String sudo_password; public static final Function toNode = new Function() { @Override public Node apply(YamlNode arg0) { if (arg0 == null) return null; return Node.builder().id(arg0.id).name(arg0.name).description(arg0.description).locationId(arg0.location_id) .hostname(arg0.hostname).osArch(arg0.os_arch).osFamily(arg0.os_family).osDescription( arg0.os_description).osVersion(arg0.os_version).os64Bit(arg0.os_64bit).group(arg0.group) .loginPort(arg0.login_port).tags(arg0.tags).metadata(arg0.metadata).username(arg0.username).credential(arg0.credential).credentialUrl( arg0.credential_url != null ? URI.create(arg0.credential_url) : null).sudoPassword( arg0.sudo_password).build(); } }; public Node toNode() { return toNode.apply(this); } public static final Function byteSourceToYamlNode = new Function() { @Override public YamlNode apply(ByteSource byteSource) { if (byteSource == null) return null; InputStream in = null; try { in = byteSource.openStream(); return (YamlNode) new Yaml(new Constructor(YamlNode.class, new LoaderOptions())).load(in); } catch (IOException ioe) { throw Throwables.propagate(ioe); } finally { Closeables2.closeQuietly(in); } } }; public static YamlNode fromYaml(ByteSource in) { return byteSourceToYamlNode.apply(in); } public static final Function yamlNodeToByteSource = new Function() { @Override public ByteSource apply(YamlNode in) { if (in == null) return null; Builder prettier = ImmutableMap.builder(); if (in.id != null) prettier.put("id", in.id); if (in.name != null) prettier.put("name", in.name); if (in.description != null) prettier.put("description", in.description); if (in.hostname != null) prettier.put("hostname", in.hostname); if (in.location_id != null) prettier.put("location_id", in.location_id); if (in.os_arch != null) prettier.put("os_arch", in.os_arch); if (in.os_family != null) prettier.put("os_family", in.os_family); if (in.os_description != null) prettier.put("os_description", in.os_description); if (in.os_version != null) prettier.put("os_version", in.os_version); if (in.os_64bit) prettier.put("os_64bit", in.os_64bit); if (in.login_port != 22) prettier.put("login_port", in.login_port); if (in.group != null) prettier.put("group", in.group); if (in.tags.size() != 0) prettier.put("tags", in.tags); if (in.metadata.size() != 0) prettier.put("metadata", in.metadata); if (in.username != null) prettier.put("username", in.username); if (in.credential != null) prettier.put("credential", in.credential); if (in.credential_url != null) prettier.put("credential_url", in.credential_url); if (in.sudo_password != null) prettier.put("sudo_password", in.sudo_password); DumperOptions options = new DumperOptions(); options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); return ByteSource.wrap(new Yaml(options).dump(prettier.build()).getBytes(Charsets.UTF_8)); } }; public ByteSource toYaml() { return yamlNodeToByteSource.apply(this); } public static YamlNode fromNode(Node in) { return nodeToYamlNode.apply(in); } public static final Function nodeToYamlNode = new Function() { @Override public YamlNode apply(Node arg0) { if (arg0 == null) return null; YamlNode yaml = new YamlNode(); yaml.id = arg0.getId(); yaml.name = arg0.getName(); yaml.description = arg0.getDescription(); yaml.hostname = arg0.getHostname(); yaml.location_id = arg0.getLocationId(); yaml.os_arch = arg0.getOsArch(); yaml.os_family = arg0.getOsFamily(); yaml.os_description = arg0.getOsDescription(); yaml.os_version = arg0.getOsVersion(); yaml.os_64bit = arg0.isOs64Bit(); yaml.login_port = arg0.getLoginPort(); yaml.group = arg0.getGroup(); yaml.tags = ImmutableList.copyOf(arg0.getTags()); yaml.metadata = ImmutableMap.copyOf(arg0.getMetadata()); yaml.username = arg0.getUsername(); yaml.credential = arg0.getCredential(); yaml.credential_url = arg0.getCredentialUrl() != null ? arg0.getCredentialUrl().toASCIIString() : null; yaml.sudo_password = arg0.getSudoPassword(); return yaml; } }; } ================================================ FILE: apis/byon/src/main/java/org/jclouds/byon/functions/NodeToNodeMetadata.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.byon.functions; import static com.google.common.base.Preconditions.checkNotNull; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; import jakarta.annotation.Resource; import jakarta.inject.Inject; import jakarta.inject.Named; import jakarta.inject.Singleton; import org.jclouds.byon.Node; import org.jclouds.collect.Memoized; import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadataBuilder; import org.jclouds.compute.domain.OperatingSystem; import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.NodeMetadata.Status; import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.domain.Credentials; import org.jclouds.domain.Location; import org.jclouds.domain.LoginCredentials; import org.jclouds.domain.LoginCredentials.Builder; import org.jclouds.logging.Logger; import org.jclouds.util.Strings2; import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.base.Supplier; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; @Singleton public class NodeToNodeMetadata implements Function { @Resource @Named(ComputeServiceConstants.COMPUTE_LOGGER) protected Logger logger = Logger.NULL; private final Supplier location; private final Supplier> locations; private final Map credentialStore; private final Function slurp; @Inject NodeToNodeMetadata(Supplier location, @Memoized Supplier> locations, Function slurp, Map credentialStore) { this.location = checkNotNull(location, "location"); this.locations = checkNotNull(locations, "locations"); this.credentialStore = checkNotNull(credentialStore, "credentialStore"); this.slurp = checkNotNull(slurp, "slurp"); } @Override public NodeMetadata apply(Node from) { NodeMetadataBuilder builder = new NodeMetadataBuilder(); builder.ids(from.getId()); builder.name(from.getName()); builder.loginPort(from.getLoginPort()); builder.hostname(from.getHostname()); builder.location(findLocationWithId(from.getLocationId())); builder.group(from.getGroup()); builder.tags(from.getTags()); builder.userMetadata(from.getMetadata()); builder.operatingSystem(OperatingSystem.builder().arch(from.getOsArch()).family( OsFamily.fromValue(from.getOsFamily())).description(from.getOsDescription()) .version(from.getOsVersion()).build()); builder.status(Status.RUNNING); builder.publicAddresses(ImmutableSet. of(from.getHostname())); if (from.getUsername() != null) { Builder credBuilder = LoginCredentials.builder().user(from.getUsername()); if (from.getCredentialUrl() != null) { try { credBuilder.credential(Strings2.toStringAndClose(slurp.apply(from.getCredentialUrl()))); } catch (IOException e) { logger.error(e, "URI could not be read: %s", from.getCredentialUrl()); } } else if (from.getCredential() != null) { credBuilder.credential(from.getCredential()); } if (from.getSudoPassword() != null) { credBuilder.password(from.getSudoPassword()); credBuilder.authenticateSudo(true); } LoginCredentials creds = credBuilder.build(); builder.credentials(creds); credentialStore.put("node#" + from.getId(), creds); } return builder.build(); } private Location findLocationWithId(final String locationId) { if (locationId == null) return location.get(); try { Location location = Iterables.find(locations.get(), new Predicate() { @Override public boolean apply(Location input) { return input.getId().equals(locationId); } }); return location; } catch (NoSuchElementException e) { logger.debug("couldn't match instance location %s in: %s", locationId, locations.get()); return location.get(); } } } ================================================ FILE: apis/byon/src/main/java/org/jclouds/byon/functions/NodesFromYamlStream.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.byon.functions; import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Throwables.propagate; import static org.jclouds.util.Closeables2.closeQuietly; import java.io.IOException; import java.io.InputStream; import java.util.List; import java.util.Map; import jakarta.inject.Singleton; import org.jclouds.byon.Node; import org.jclouds.byon.domain.YamlNode; import org.yaml.snakeyaml.LoaderOptions; import org.yaml.snakeyaml.TypeDescription; import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.constructor.Constructor; import com.google.common.base.Function; import com.google.common.base.Functions; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.collect.Iterables; import com.google.common.collect.Maps; import com.google.common.io.ByteSource; /** * Parses the following syntax. * *
 * nodes:
 *     - id: cluster-1:
 *       name: cluster-1
 *       description: xyz
 *       hostname: cluster-1.mydomain.com
 *       location_id: virginia
 *       os_arch: x86
 *       os_family: linux
 *       os_description: redhat
 *       os_version: 5.3
 *       group: hadoop
 *       tags:
 *           - vanilla
 *       username: kelvin
 *       credential: password_or_rsa
 *         or
 *       credential_url: password_or_rsa_file ex. resource:///id_rsa will get the classpath /id_rsa; file://path/to/id_rsa
 *       sudo_password: password
 * 
*/ @Singleton public class NodesFromYamlStream implements Function> { /** * Type-safe config class for YAML * */ public static class Config { public List nodes; } @Override public LoadingCache apply(ByteSource source) { Constructor constructor = new Constructor(Config.class, new LoaderOptions()); TypeDescription nodeDesc = new TypeDescription(YamlNode.class); nodeDesc.putListPropertyType("tags", String.class); constructor.addTypeDescription(nodeDesc); TypeDescription configDesc = new TypeDescription(Config.class); configDesc.putListPropertyType("nodes", YamlNode.class); constructor.addTypeDescription(configDesc); Yaml yaml = new Yaml(constructor); Config config; InputStream in = null; try { in = source.openStream(); config = (Config) yaml.load(in); } catch (IOException ioe) { throw propagate(ioe); } finally { closeQuietly(in); } checkState(config != null, "missing config: class"); checkState(config.nodes != null, "missing nodes: collection"); Map backingMap = Maps.uniqueIndex(Iterables.transform(config.nodes, YamlNode.toNode), new Function() { public String apply(Node node) { return node.getId(); } }); LoadingCache cache = CacheBuilder.newBuilder().build(CacheLoader.from(Functions.forMap(backingMap))); for (String node : backingMap.keySet()) cache.getUnchecked(node); return cache; } } ================================================ FILE: apis/byon/src/main/java/org/jclouds/byon/internal/BYONComputeServiceAdapter.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.byon.internal; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Predicates.in; import static com.google.common.collect.Iterables.filter; import static com.google.common.collect.Iterables.getOnlyElement; import static com.google.common.collect.Iterables.transform; import static com.google.common.collect.Maps.filterKeys; import java.util.Set; import jakarta.inject.Inject; import jakarta.inject.Singleton; import org.jclouds.byon.Node; import org.jclouds.byon.functions.NodeToNodeMetadata; import org.jclouds.compute.JCloudsNativeComputeServiceAdapter; import org.jclouds.compute.domain.Hardware; import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.Template; import org.jclouds.domain.Location; import org.jclouds.domain.LocationBuilder; import org.jclouds.domain.LocationScope; import org.jclouds.location.suppliers.all.JustProvider; import com.google.common.base.Function; import com.google.common.base.Predicates; import com.google.common.base.Supplier; import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet.Builder; import com.google.common.util.concurrent.UncheckedExecutionException; @Singleton public class BYONComputeServiceAdapter implements JCloudsNativeComputeServiceAdapter { private final Supplier> nodes; private final NodeToNodeMetadata converter; private final JustProvider locationSupplier; @Inject public BYONComputeServiceAdapter(Supplier> nodes, NodeToNodeMetadata converter, JustProvider locationSupplier) { this.nodes = checkNotNull(nodes, "nodes"); this.converter = checkNotNull(converter, "converter"); this.locationSupplier = checkNotNull(locationSupplier, "locationSupplier"); } @Override public NodeWithInitialCredentials createNodeWithGroupEncodedIntoName(String group, String name, Template template) { throw new UnsupportedOperationException(); } @Override public Iterable listHardwareProfiles() { return ImmutableSet. of(); } @Override public Iterable listImages() { return ImmutableSet. of(); } @Override public Iterable listNodes() { return transform(nodes.get().asMap().values(), converter); } @Override public Iterable listNodesByIds(Iterable ids) { return transform(filterKeys(nodes.get().asMap(), in(ImmutableSet.copyOf(ids))).values(), converter); } @Override public Iterable listLocations() { Builder locations = ImmutableSet.builder(); Location provider = getOnlyElement(locationSupplier.get()); Set zones = ImmutableSet.copyOf(filter(transform(nodes.get().asMap().values(), new Function() { @Override public String apply(Node arg0) { return arg0.getLocationId(); } }), Predicates.notNull())); if (zones.isEmpty()) return locations.add(provider).build(); else for (String zone : zones) { locations.add(new LocationBuilder().scope(LocationScope.ZONE).id(zone).description(zone).parent(provider) .build()); } return locations.build(); } @Override public NodeMetadata getNode(String id) { Node node = null; try { node = nodes.get().getUnchecked(id); } catch (UncheckedExecutionException e) { } return node != null ? converter.apply(node) : null; } @Override public Image getImage(final String id) { throw new UnsupportedOperationException(); } @Override public void destroyNode(final String id) { throw new UnsupportedOperationException(); } @Override public void rebootNode(String id) { throw new UnsupportedOperationException(); } @Override public void resumeNode(String id) { throw new UnsupportedOperationException(); } @Override public void suspendNode(String id) { throw new UnsupportedOperationException(); } } ================================================ FILE: apis/byon/src/main/java/org/jclouds/byon/suppliers/NodesParsedFromSupplier.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.byon.suppliers; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; import jakarta.annotation.Resource; import jakarta.inject.Inject; import jakarta.inject.Singleton; import org.jclouds.byon.Node; import org.jclouds.location.Provider; import org.jclouds.logging.Logger; import com.google.common.base.Function; import com.google.common.base.Supplier; import com.google.common.cache.LoadingCache; import com.google.common.io.ByteSource; @Singleton public class NodesParsedFromSupplier implements Supplier> { @Resource protected Logger logger = Logger.NULL; private final ByteSource supplier; private final Function> parser; @Inject NodesParsedFromSupplier(@Provider ByteSource supplier, Function> parser) { this.supplier = checkNotNull(supplier, "supplier"); this.parser = checkNotNull(parser, "parser"); } @Override public LoadingCache get() { LoadingCache nodes = parser.apply(supplier); checkState(nodes != null && nodes.size() > 0, "no nodes parsed from supplier: %s", supplier); return nodes; } } ================================================ FILE: apis/byon/src/main/java/org/jclouds/byon/suppliers/SupplyFromProviderURIOrNodesProperty.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.byon.suppliers; import static com.google.common.base.Preconditions.checkNotNull; import java.io.IOException; import java.io.InputStream; import java.net.URI; import jakarta.annotation.Resource; import org.jclouds.location.Provider; import org.jclouds.logging.Logger; import org.jclouds.util.Strings2; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Function; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; import com.google.common.base.Throwables; import com.google.common.io.ByteSource; import com.google.inject.Inject; import com.google.inject.name.Named; public class SupplyFromProviderURIOrNodesProperty extends ByteSource implements Function { @Resource protected Logger logger = Logger.NULL; private final Supplier url; @Inject(optional = true) @Named("byon.nodes") @VisibleForTesting String nodes; @VisibleForTesting public SupplyFromProviderURIOrNodesProperty(URI url) { this(Suppliers.ofInstance(checkNotNull(url, "url"))); } @Inject public SupplyFromProviderURIOrNodesProperty(@Provider Supplier url) { this.url = checkNotNull(url, "url"); } @Override public InputStream openStream() { if (nodes != null) return Strings2.toInputStream(nodes); return apply(url.get()); } @Override public String toString() { return "[url=" + url + "]"; } @Override public InputStream apply(URI input) { try { if (input.getScheme() != null && input.getScheme().equals("classpath")) return getClass().getResourceAsStream(input.getPath()); return input.toURL().openStream(); } catch (IOException e) { logger.error(e, "URI could not be read: %s", url); throw Throwables.propagate(e); } } } ================================================ FILE: apis/byon/src/test/java/org/jclouds/byon/BYONApiMetadataTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.byon; import org.jclouds.compute.internal.BaseComputeServiceApiMetadataTest; import org.testng.annotations.Test; @Test(groups = "unit", testName = "BYONApiMetadataTest") public class BYONApiMetadataTest extends BaseComputeServiceApiMetadataTest { public BYONApiMetadataTest() { super(new BYONApiMetadata()); } } ================================================ FILE: apis/byon/src/test/java/org/jclouds/byon/BYONComputeServiceLiveTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.byon; import static org.jclouds.compute.options.RunScriptOptions.Builder.wrapInInitScript; import static org.jclouds.scriptbuilder.domain.Statements.exec; import java.io.FileNotFoundException; import java.io.IOException; import java.util.Map; import java.util.Properties; import java.util.Map.Entry; import org.jclouds.ContextBuilder; import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.domain.ExecResponse; import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.logging.log4j.config.Log4JLoggingModule; import org.jclouds.scriptbuilder.domain.OsFamily; import org.jclouds.sshj.config.SshjSshClientModule; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import com.google.common.base.Predicates; import com.google.common.collect.ImmutableSet; import com.google.inject.Module; @Test(groups = "live") public class BYONComputeServiceLiveTest { private ComputeServiceContext context; @BeforeClass(groups = "live") public void setup() throws FileNotFoundException, IOException { Properties contextProperties = new Properties(); StringBuilder nodes = new StringBuilder(); nodes.append("nodes:\n"); nodes.append(" - id: mymachine\n"); nodes.append(" name: my local machine\n"); nodes.append(" hostname: localhost\n"); nodes.append(" os_arch: ").append(System.getProperty("os.arch")).append("\n"); nodes.append(" os_family: ").append(OsFamily.UNIX).append("\n"); nodes.append(" os_description: ").append(System.getProperty("os.name")).append("\n"); nodes.append(" os_version: ").append(System.getProperty("os.version")).append("\n"); nodes.append(" group: ").append("ssh").append("\n"); nodes.append(" tags:\n"); nodes.append(" - local\n"); nodes.append(" username: ").append(System.getProperty("user.name")).append("\n"); nodes.append(" credential_url: file://").append(System.getProperty("user.home")).append("/.ssh/id_rsa") .append("\n"); contextProperties.setProperty("byon.nodes", nodes.toString()); context = ContextBuilder.newBuilder(new BYONApiMetadata()).overrides(contextProperties).modules( ImmutableSet. of(new SshjSshClientModule(), new Log4JLoggingModule())).build( ComputeServiceContext.class); } public void testCanRunCommandAsCurrentUser() throws Exception { Map responses = context.getComputeService().runScriptOnNodesMatching( Predicates. alwaysTrue(), exec("id"), wrapInInitScript(false).runAsRoot(false)); for (Entry response : responses.entrySet()) assert response.getValue().getOutput().trim().contains(System.getProperty("user.name")) : response.getKey() + ": " + response.getValue(); } @AfterClass(groups = "live") public void close() throws FileNotFoundException, IOException { if (context != null) context.close(); } } ================================================ FILE: apis/byon/src/test/java/org/jclouds/byon/BYONComputeServiceTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.byon; import static org.jclouds.byon.functions.NodeToNodeMetadataTest.expectedNodeMetadataFromResource; import static org.jclouds.byon.functions.NodeToNodeMetadataTest.expectedProviderLocationFromResource; import static org.jclouds.byon.functions.NodeToNodeMetadataTest.zoneCalled; import static org.testng.Assert.assertEquals; import org.jclouds.ContextBuilder; import org.jclouds.byon.config.BYONComputeServiceContextModule; import org.jclouds.byon.config.CacheNodeStoreModule; import org.jclouds.byon.functions.NodesFromYamlTest; import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.domain.Location; import org.jclouds.domain.LoginCredentials; import org.testng.annotations.Test; import com.google.common.base.Supplier; import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.inject.Key; import com.google.inject.Module; import com.google.inject.TypeLiteral; @Test(singleThreaded = true, testName = "BYONComputeServiceTest") public class BYONComputeServiceTest { @Test public void testNodesParseNodeMap() throws Exception { assertNodesParse("foo", ContextBuilder.newBuilder( new BYONApiMetadata().toBuilder().defaultModule(BYONComputeServiceContextModule.class).build()) .endpoint("foo").modules( ImmutableSet. of(new CacheNodeStoreModule(ImmutableMap. of( NodesFromYamlTest.TEST1.getId(), NodesFromYamlTest.TEST1)))).build( ComputeServiceContext.class)); } @Test public void testNodesParseWithFileUrl() throws Exception { assertNodesParse("file://" + getClass().getResource("/test1.yaml").getPath(), ContextBuilder.newBuilder(new BYONApiMetadata()).endpoint( "file://" + getClass().getResource("/test1.yaml").getPath()).build(ComputeServiceContext.class)); } @Test public void testNodesParseWithClasspathUrl() throws Exception { assertNodesParse("classpath:///test1.yaml", ContextBuilder.newBuilder(new BYONApiMetadata()).endpoint( "classpath:///test1.yaml").build(ComputeServiceContext.class)); } private void assertNodesParse(String endpoint, ComputeServiceContext context) { try { Location providerLocation = expectedProviderLocationFromResource(endpoint); Supplier> supplier = supplier(context); assertEquals(supplier.get().size(), context.getComputeService().listNodes().size()); assertEquals(supplier.get().asMap(), ImmutableMap. of(NodesFromYamlTest.TEST1.getId(), NodesFromYamlTest.TEST1)); assertEquals(context.getComputeService().listNodes().toString(), ImmutableSet.of(expectedNodeMetadataFromResource(endpoint)).toString()); assertEquals(context.getComputeService().listAssignableLocations(), ImmutableSet.of(providerLocation)); } finally { if (context != null) context.close(); } } public void testNodesWithLocations() { ComputeServiceContext context = null; try { String endpoint = "file://" + getClass().getResource("/test_location.yaml").getPath(); context = ContextBuilder.newBuilder(new BYONApiMetadata()).endpoint(endpoint).build(ComputeServiceContext.class); Supplier> supplier = supplier(context); assertEquals(supplier.get().size(), context.getComputeService().listNodes().size()); assertEquals(supplier.get().asMap(), ImmutableMap. of(NodesFromYamlTest.TEST2.getId(), NodesFromYamlTest.TEST2, NodesFromYamlTest.TEST3.getId(), NodesFromYamlTest.TEST3)); Location providerLocation = expectedProviderLocationFromResource(endpoint); Location virginia = zoneCalled("virginia", providerLocation); Location maryland = zoneCalled("maryland", providerLocation); assertEquals( context.getComputeService().listNodes().toString(), ImmutableSet.of(expectedNodeMetadataFromResource(1, endpoint, virginia), expectedNodeMetadataFromResource(2, endpoint, maryland, 2022)).toString()); assertEquals(NodeMetadata.class.cast(Iterables.get(context.getComputeService().listNodes(), 0)) .getCredentials(), LoginCredentials .builder() .user("myUser") .password("happy bear") .authenticateSudo(true) .privateKey( "-----BEGIN RSA PRIVATE KEY-----\n" + "MIIEowIBAAKCAQEAuzaE6azgUxwESX1rCGdJ5xpdrc1XC311bOGZBCE8NA+CpFh2\n" + "u01Vfv68NC4u6LFgdXSY1vQt6hiA5TNqQk0TyVfFAunbXgTekF6XqDPQUf1nq9aZ\n" + "lMvo4vlaLDKBkhG5HJE/pIa0iB+RMZLS0GhxsIWerEDmYdHKM25o\n" + "-----END RSA PRIVATE KEY-----\n").build() ); assertEquals(context.getComputeService().listAssignableLocations(), ImmutableSet.of(virginia, maryland)); } finally { if (context != null) context.close(); } } private Supplier> supplier(ComputeServiceContext context) { Supplier> supplier = context.utils().injector().getInstance( Key.get(new TypeLiteral>>() { })); return supplier; } } ================================================ FILE: apis/byon/src/test/java/org/jclouds/byon/config/CacheNodeStoreModuleTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.byon.config; import static org.testng.Assert.assertEquals; import static org.testng.Assert.fail; import java.io.IOException; import java.util.Map; import org.jclouds.byon.Node; import org.jclouds.location.Provider; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import com.google.common.base.Functions; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.collect.Maps; import com.google.common.io.ByteSource; import com.google.common.util.concurrent.UncheckedExecutionException; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.TypeLiteral; import com.google.inject.util.Providers; @Test(groups = "unit", singleThreaded = true, testName = "CacheNodeStoreModuleTest") public class CacheNodeStoreModuleTest { @DataProvider(name = "names") public Object[][] createData() { return new Object[][] { { "instance1", "bear" }, { "instance2", "apple" }, { "instance2", "francis" }, { "instance4", "robot" } }; } public void testProvidedMapWithValue() throws IOException { Map map = Maps.newConcurrentMap(); map.put("test", Node.builder().id("instance1").name("instancename").build()); checkConsistent(map, getStore(createInjectorWithProvidedMap(map)), "test", "instance1", "instancename"); checkConsistent(map, getStore(createInjectorWithProvidedMap(map)), "test", "instance1", "instancename"); remove(map, getStore(createInjectorWithProvidedMap(map)), "test"); } public void testProvidedConsistentAcrossRepeatedWrites() throws IOException { Map map = Maps.newConcurrentMap(); Injector injector = createInjectorWithProvidedMap(map); assertEquals(injector.getInstance(Key.get(new TypeLiteral>() { })).asMap(), map); LoadingCache store = getStore(injector); for (int i = 0; i < 10; i++) check(map, store, "test" + i, "instance1" + i, "instancename" + i); } public void testProvidedConsistentAcrossMultipleInjectors() throws IOException { Map map = Maps.newConcurrentMap(); put(map, getStore(createInjectorWithProvidedMap(map)), "test", "instance1", "instancename"); checkConsistent(map, getStore(createInjectorWithProvidedMap(map)), "test", "instance1", "instancename"); checkConsistent(map, getStore(createInjectorWithProvidedMap(map)), "test", "instance1", "instancename"); remove(map, getStore(createInjectorWithProvidedMap(map)), "test"); } public void testProvidedCacheConsistentAcrossMultipleInjectors() throws IOException { Map map = Maps.newConcurrentMap(); LoadingCache cache = CacheBuilder.newBuilder().build(CacheLoader.from(Functions.forMap(map))); put(map, getStore(createInjectorWithProvidedCache(cache)), "test", "instance1", "instancename"); checkConsistent(map, getStore(createInjectorWithProvidedCache(cache)), "test", "instance1", "instancename"); checkConsistent(map, getStore(createInjectorWithProvidedCache(cache)), "test", "instance1", "instancename"); remove(map, getStore(createInjectorWithProvidedCache(cache)), "test"); } private LoadingCache getStore(Injector injector) { return injector.getInstance(Key.get(new TypeLiteral>() { })); } private Injector createInjectorWithProvidedMap(Map map) { return Guice.createInjector(new CacheNodeStoreModule(map), new AbstractModule() { @Override public void configure() { bind(ByteSource.class).annotatedWith(Provider.class).toProvider(Providers.of(null)); } }); } private Injector createInjectorWithProvidedCache(LoadingCache cache) { return Guice.createInjector(new CacheNodeStoreModule(cache), new AbstractModule() { @Override public void configure() { bind(ByteSource.class).annotatedWith(Provider.class).toProvider(Providers.of(null)); } }); } private void check(Map map, LoadingCache store, String key, String id, String name) throws IOException { put(map, store, key, id, name); checkConsistent(map, store, key, id, name); remove(map, store, key); } private void remove(Map map, LoadingCache store, String key) { store.invalidate(key); assertEquals(store.size(), 0); map.remove(key); assertEquals(map.size(), 0); try { assertEquals(store.getUnchecked(key), null); fail("should not work as null is invalid"); } catch (UncheckedExecutionException e) { } assertEquals(map.get(key), null); } private void checkConsistent(Map map, LoadingCache store, String key, String id, String name) throws IOException { assertEquals(map.size(), 1); if (store.size() == 0) store.getUnchecked(key); assertEquals(store.size(), 1); // checkRepeatedRead assertEquals(store.getUnchecked(key), Node.builder().id(id).name(name).build()); assertEquals(store.getUnchecked(key), Node.builder().id(id).name(name).build()); } private void put(Map map, LoadingCache store, String key, String id, String name) { assertEquals(store.size(), 0); assertEquals(map.size(), 0); map.put(key, Node.builder().id(id).name(name).build()); store.getUnchecked(key); } } ================================================ FILE: apis/byon/src/test/java/org/jclouds/byon/config/YamlNodeStoreModuleTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.byon.config; import static org.testng.Assert.assertEquals; import static org.testng.Assert.fail; import java.io.IOException; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.jclouds.byon.Node; import org.jclouds.location.Provider; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import org.yaml.snakeyaml.Yaml; import com.google.common.base.Charsets; import com.google.common.cache.LoadingCache; import com.google.common.io.ByteSource; import com.google.common.util.concurrent.UncheckedExecutionException; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.TypeLiteral; import com.google.inject.name.Names; import com.google.inject.util.Providers; @Test(groups = "unit", singleThreaded = true) public class YamlNodeStoreModuleTest { Yaml yaml = createInjector().getInstance(Yaml.class); @DataProvider(name = "names") public Object[][] createData() { return new Object[][] { { "instance1", "bear" }, { "instance2", "apple" }, { "instance2", "francis" }, { "instance4", "robot" } }; } @Test(dataProvider = "names") public void deleteObject(String id, String name) throws InterruptedException, IOException { Injector injector = createInjector(); Map map = getMap(injector); check(map, getStore(injector), "i-20312", id, name); } public void testProvidedMapWithValue() throws IOException { Map map = new ConcurrentHashMap(); map.put("test", ByteSource.wrap("id: instance1\nname: instancename\n".getBytes())); checkConsistent(map, getStore(createInjectorWithProvidedMap(map)), "test", "instance1", "instancename"); checkConsistent(map, getStore(createInjectorWithProvidedMap(map)), "test", "instance1", "instancename"); remove(map, getStore(createInjectorWithProvidedMap(map)), "test"); } public void testProvidedConsistentAcrossRepeatedWrites() throws IOException { Map map = new ConcurrentHashMap(); Injector injector = createInjectorWithProvidedMap(map); assertEquals(injector.getInstance(Key.get(new TypeLiteral>() { }, Names.named("yaml"))), map); LoadingCache store = getStore(injector); for (int i = 0; i < 10; i++) check(map, store, "test" + i, "instance1" + i, "instancename" + i); } public void testProvidedConsistentAcrossMultipleInjectors() throws IOException { Map map = new ConcurrentHashMap(); put(map, getStore(createInjectorWithProvidedMap(map)), "test", "instance1", "instancename"); checkConsistent(map, getStore(createInjectorWithProvidedMap(map)), "test", "instance1", "instancename"); checkConsistent(map, getStore(createInjectorWithProvidedMap(map)), "test", "instance1", "instancename"); remove(map, getStore(createInjectorWithProvidedMap(map)), "test"); } public void testDefaultConsistentAcrossMultipleInjectors() throws IOException { Map map = getMap(createInjector()); put(map, getStore(createInjector()), "test", "instance1", "instancename"); checkConsistent(map, getStore(createInjector()), "test", "instance1", "instancename"); checkConsistent(map, getStore(createInjector()), "test", "instance1", "instancename"); remove(map, getStore(createInjector()), "test"); } protected LoadingCache getStore(Injector injector) { return injector.getInstance(Key.get(new TypeLiteral>() { })); } protected Map getMap(Injector injector) { return injector.getInstance(Key.get(new TypeLiteral>() { }, Names.named("yaml"))); } protected Injector createInjectorWithProvidedMap(Map map) { return Guice.createInjector(new YamlNodeStoreModule(map), new AbstractModule() { @Override protected void configure() { bind(ByteSource.class).annotatedWith(Provider.class).toProvider(Providers.of(null)); } }); } protected Injector createInjector() { return Guice.createInjector(new YamlNodeStoreModule(), new AbstractModule() { @Override protected void configure() { bind(ByteSource.class).annotatedWith(Provider.class).toProvider(Providers.of(null)); } }); } protected void check(Map map, LoadingCache store, String key, String id, String name) throws IOException { put(map, store, key, id, name); checkConsistent(map, store, key, id, name); remove(map, store, key); } protected void remove(Map map, LoadingCache store, String key) { store.invalidate(key); assertEquals(store.size(), 0); map.remove(key); assertEquals(map.size(), 0); try { assertEquals(store.getUnchecked(key), null); fail("should not work as null is invalid"); } catch (UncheckedExecutionException e) { } assertEquals(map.get(key), null); } protected void checkConsistent(Map map, LoadingCache store, String key, String id, String name) throws IOException { assertEquals(map.size(), 1); if (store.size() == 0) store.getUnchecked(key); assertEquals(store.size(), 1); // checkRepeatedRead assertEquals(store.getUnchecked(key), Node.builder().id(id).name(name).build()); assertEquals(store.getUnchecked(key), Node.builder().id(id).name(name).build()); // checkRepeatedRead checkToYaml(map, key, id, name); checkToYaml(map, key, id, name); } protected void checkToYaml(Map map, String key, String id, String name) throws IOException { assertEquals(map.get(key).asCharSource(Charsets.UTF_8).read(), String.format("id: %s\nname: %s\n", id, name)); } protected void put(Map map, LoadingCache store, String key, String id, String name) { assertEquals(store.size(), 0); assertEquals(map.size(), 0); map.put(key, ByteSource.wrap(String.format("id: %s\nname: %s\n", id, name).getBytes())); store.getUnchecked(key); } } ================================================ FILE: apis/byon/src/test/java/org/jclouds/byon/functions/NodeToNodeMetadataTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.byon.functions; import static org.testng.Assert.assertEquals; import java.net.URI; import java.util.Map; import java.util.Set; import org.jclouds.byon.suppliers.SupplyFromProviderURIOrNodesProperty; import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadataBuilder; import org.jclouds.compute.domain.OperatingSystem; import org.jclouds.compute.domain.OsFamily; import org.jclouds.compute.domain.NodeMetadata.Status; import org.jclouds.domain.Credentials; import org.jclouds.domain.Location; import org.jclouds.domain.LocationBuilder; import org.jclouds.domain.LocationScope; import org.jclouds.domain.LoginCredentials; import org.testng.annotations.Test; import com.google.common.base.Suppliers; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; @Test(singleThreaded = true, testName = "NodeToNodeMetadataTest") public class NodeToNodeMetadataTest { public static Location expectedProviderLocationFromResource(String resource) { return new LocationBuilder().scope(LocationScope.PROVIDER).id("byon").description(resource).build(); } public static Location zoneCalled(String zone, Location parent) { return new LocationBuilder().scope(LocationScope.ZONE).id(zone).description(zone).parent(parent).build(); } String resource = "location"; Location provider = expectedProviderLocationFromResource(resource); Map credentialStore = Maps.newLinkedHashMap(); NodeToNodeMetadata parser = new NodeToNodeMetadata(Suppliers.ofInstance(provider), Suppliers.> ofInstance(ImmutableSet.of(provider, zoneCalled("virginia", provider))), new SupplyFromProviderURIOrNodesProperty(URI.create("test")), credentialStore); public static NodeMetadata expectedNodeMetadataFromResource(String resource) { return expectedNodeMetadataFromResource(resource, expectedProviderLocationFromResource(resource)); } public static NodeMetadata expectedNodeMetadataFromResource(String resource, Location location) { return expectedNodeMetadataFromResource(1, resource, location); } public static NodeMetadata expectedNodeMetadataFromResource(int id, String resource, Location location) { return expectedNodeMetadataFromResource(id, resource, location, 22); } public static NodeMetadata expectedNodeMetadataFromResource(int id, String resource, Location location, int loginPort) { return new NodeMetadataBuilder() .ids("cluster-" + id) .group("hadoop") .name("cluster-" + id) .loginPort(loginPort) .hostname("cluster-" + id + ".mydomain.com") .location(location) .userMetadata(ImmutableMap.of("Name", "foo")) .tags(ImmutableSet.of("vanilla")) .status(Status.RUNNING) .operatingSystem( OperatingSystem.builder().description("redhat").family(OsFamily.RHEL).arch("x86").version("5.3") .build()) .publicAddresses(ImmutableSet.of("cluster-" + id + ".mydomain.com")) .credentials( LoginCredentials.builder().user("myUser").privateKey(NodesFromYamlTest.key).password("happy bear") .authenticateSudo(true).build()).build(); } @Test public void testNodesParse() throws Exception { assertEquals(parser.apply(NodesFromYamlTest.TEST1), expectedNodeMetadataFromResource(resource, provider)); assertEquals(credentialStore, ImmutableMap.of("node#cluster-1", new Credentials("myUser", NodesFromYamlTest.key))); } @Test public void testNodesParseLocation() throws Exception { assertEquals(parser.apply(NodesFromYamlTest.TEST2), expectedNodeMetadataFromResource(resource, zoneCalled("virginia", provider))); assertEquals(credentialStore, ImmutableMap.of("node#cluster-1", new Credentials("myUser", NodesFromYamlTest.key))); } @Test public void testNodesParseLoginPort() throws Exception { assertEquals(parser.apply(NodesFromYamlTest.TEST3), expectedNodeMetadataFromResource(2, resource, provider, 2022)); } } ================================================ FILE: apis/byon/src/test/java/org/jclouds/byon/functions/NodesFromYamlTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.byon.functions; import static org.testng.Assert.assertEquals; import org.jclouds.byon.Node; import org.testng.annotations.Test; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.io.ByteSource; import com.google.common.io.Resources; public class NodesFromYamlTest { public static final String key = new StringBuilder().append("-----BEGIN RSA PRIVATE KEY-----\n") .append("MIIEowIBAAKCAQEAuzaE6azgUxwESX1rCGdJ5xpdrc1XC311bOGZBCE8NA+CpFh2\n") .append("u01Vfv68NC4u6LFgdXSY1vQt6hiA5TNqQk0TyVfFAunbXgTekF6XqDPQUf1nq9aZ\n") .append("lMvo4vlaLDKBkhG5HJE/pIa0iB+RMZLS0GhxsIWerEDmYdHKM25o\n").append("-----END RSA PRIVATE KEY-----\n") .toString(); public static final Node TEST1 = new Node("cluster-1", "cluster-1", "accounting analytics cluster", "cluster-1.mydomain.com", null, "x86", "rhel", "redhat", "5.3", false, 22, "hadoop", ImmutableList.of("vanilla"), ImmutableMap.of("Name", "foo"), "myUser", key, null, "happy bear"); public static final Node TEST2 = new Node("cluster-1", "cluster-1", "accounting analytics cluster", "cluster-1.mydomain.com", "virginia", "x86", "rhel", "redhat", "5.3", false, 22, "hadoop", ImmutableList.of("vanilla"), ImmutableMap.of("Name", "foo"), "myUser", key, null, "happy bear"); public static final Node TEST3 = new Node("cluster-2", "cluster-2", "accounting analytics cluster", "cluster-2.mydomain.com", "maryland", "x86", "rhel", "redhat", "5.3", false, 2022, "hadoop", ImmutableList.of("vanilla"), ImmutableMap.of("Name", "foo"), "myUser", key, null, "happy bear"); @Test public void testNodesParse() throws Exception { ByteSource byteSource = Resources.asByteSource(Resources.getResource("test1.yaml")); NodesFromYamlStream parser = new NodesFromYamlStream(); assertEquals(parser.apply(byteSource).asMap(), ImmutableMap.of(TEST1.getId(), TEST1)); } @Test public void testNodesParseLocation() throws Exception { ByteSource byteSource = Resources.asByteSource(Resources.getResource("test_location.yaml")); NodesFromYamlStream parser = new NodesFromYamlStream(); assertEquals(parser.apply(byteSource).asMap(), ImmutableMap.of(TEST2.getId(), TEST2, TEST3.getId(), TEST3)); } @Test public void testNodesParseWhenCredentialInUrl() throws Exception { ByteSource byteSource = Resources.asByteSource(Resources.getResource("test_with_url.yaml")); NodesFromYamlStream parser = new NodesFromYamlStream(); assertEquals(parser.apply(byteSource).asMap(), ImmutableMap.of(TEST1.getId(), TEST1)); } @Test(expectedExceptions = IllegalStateException.class) public void testMustParseSomething() throws Exception { new NodesFromYamlStream().apply(ByteSource.empty()); } } ================================================ FILE: apis/byon/src/test/java/org/jclouds/byon/suppliers/NodesParsedFromSupplierTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.byon.suppliers; import org.jclouds.byon.functions.NodesFromYamlStream; import org.testng.annotations.Test; import com.google.common.base.Charsets; import com.google.common.io.ByteSource; public class NodesParsedFromSupplierTest { @Test(expectedExceptions = IllegalStateException.class) public void testMustParseSomething() throws Exception { new NodesParsedFromSupplier(ByteSource.wrap("nodes:\n".getBytes(Charsets.UTF_8)), new NodesFromYamlStream()).get(); } } ================================================ FILE: apis/byon/src/test/java/org/jclouds/byon/suppliers/SupplyFromProviderURIOrNodesPropertyTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.byon.suppliers; import static org.testng.Assert.assertEquals; import java.net.URI; import com.google.common.base.Charsets; import org.jclouds.util.Strings2; import org.testng.annotations.Test; public class SupplyFromProviderURIOrNodesPropertyTest { @Test public void testFromURI() throws Exception { String path = getClass().getResource("/test1.yaml").getPath(); SupplyFromProviderURIOrNodesProperty supplier = new SupplyFromProviderURIOrNodesProperty(URI.create("file://" + path)); assertEquals(supplier.asCharSource(Charsets.UTF_8).read(), Strings2.toStringAndClose(getClass().getResourceAsStream( "/test1.yaml"))); } @Test public void testFromURIClasspath() throws Exception { SupplyFromProviderURIOrNodesProperty supplier = new SupplyFromProviderURIOrNodesProperty(URI .create("classpath:///test1.yaml")); assertEquals(supplier.asCharSource(Charsets.UTF_8).read(), Strings2.toStringAndClose(getClass().getResourceAsStream( "/test1.yaml"))); } @Test public void testFromProperty() throws Exception { SupplyFromProviderURIOrNodesProperty supplier = new SupplyFromProviderURIOrNodesProperty(URI.create("file://bar")); supplier.nodes = Strings2.toStringAndClose(getClass().getResourceAsStream("/test1.yaml")); assertEquals(supplier.asCharSource(Charsets.UTF_8).read(), Strings2.toStringAndClose(getClass().getResourceAsStream( "/test1.yaml"))); } @Test public void testSupplyMultipleTimes() throws Exception { String path = getClass().getResource("/test1.yaml").getPath(); SupplyFromProviderURIOrNodesProperty supplier = new SupplyFromProviderURIOrNodesProperty(URI.create("file://" + path)); for (int i = 0; i < 5; i++) assertEquals(supplier.asCharSource(Charsets.UTF_8).read(), Strings2.toStringAndClose(getClass() .getResourceAsStream("/test1.yaml"))); } } ================================================ FILE: apis/byon/src/test/resources/log4j.xml ================================================ ================================================ FILE: apis/byon/src/test/resources/test1.yaml ================================================ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # nodes: - id: cluster-1 name: cluster-1 description: accounting analytics cluster hostname: cluster-1.mydomain.com os_arch: x86 os_family: rhel os_description: redhat os_version: 5.3 group: hadoop tags: - vanilla metadata: Name: foo username: myUser credential: | -----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEAuzaE6azgUxwESX1rCGdJ5xpdrc1XC311bOGZBCE8NA+CpFh2 u01Vfv68NC4u6LFgdXSY1vQt6hiA5TNqQk0TyVfFAunbXgTekF6XqDPQUf1nq9aZ lMvo4vlaLDKBkhG5HJE/pIa0iB+RMZLS0GhxsIWerEDmYdHKM25o -----END RSA PRIVATE KEY----- sudo_password: happy bear ================================================ FILE: apis/byon/src/test/resources/test_location.yaml ================================================ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # nodes: - id: cluster-1 name: cluster-1 description: accounting analytics cluster hostname: cluster-1.mydomain.com location_id: virginia os_arch: x86 os_family: rhel os_description: redhat os_version: 5.3 group: hadoop tags: - vanilla metadata: Name: foo username: myUser credential: | -----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEAuzaE6azgUxwESX1rCGdJ5xpdrc1XC311bOGZBCE8NA+CpFh2 u01Vfv68NC4u6LFgdXSY1vQt6hiA5TNqQk0TyVfFAunbXgTekF6XqDPQUf1nq9aZ lMvo4vlaLDKBkhG5HJE/pIa0iB+RMZLS0GhxsIWerEDmYdHKM25o -----END RSA PRIVATE KEY----- sudo_password: happy bear - id: cluster-2 name: cluster-2 description: accounting analytics cluster hostname: cluster-2.mydomain.com location_id: maryland os_arch: x86 os_family: rhel os_description: redhat os_version: 5.3 login_port: 2022 group: hadoop tags: - vanilla metadata: Name: foo username: myUser credential: | -----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEAuzaE6azgUxwESX1rCGdJ5xpdrc1XC311bOGZBCE8NA+CpFh2 u01Vfv68NC4u6LFgdXSY1vQt6hiA5TNqQk0TyVfFAunbXgTekF6XqDPQUf1nq9aZ lMvo4vlaLDKBkhG5HJE/pIa0iB+RMZLS0GhxsIWerEDmYdHKM25o -----END RSA PRIVATE KEY----- sudo_password: happy bear ================================================ FILE: apis/byon/src/test/resources/test_with_url.yaml ================================================ # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # nodes: - id: cluster-1 name: cluster-1 description: accounting analytics cluster hostname: cluster-1.mydomain.com os_arch: x86 os_family: rhel os_description: redhat os_version: 5.3 group: hadoop tags: - vanilla metadata: Name: foo username: myUser credential_url: classpath:///testkey.txt sudo_password: happy bear ================================================ FILE: apis/byon/src/test/resources/testkey.txt ================================================ -----BEGIN RSA PRIVATE KEY----- MIIEowIBAAKCAQEAuzaE6azgUxwESX1rCGdJ5xpdrc1XC311bOGZBCE8NA+CpFh2 u01Vfv68NC4u6LFgdXSY1vQt6hiA5TNqQk0TyVfFAunbXgTekF6XqDPQUf1nq9aZ lMvo4vlaLDKBkhG5HJE/pIa0iB+RMZLS0GhxsIWerEDmYdHKM25o -----END RSA PRIVATE KEY----- ================================================ FILE: apis/chef/bnd.bnd ================================================ Export-Package: \ org.jclouds.chef.*;version="${project.version}";-noimport:=true, \ org.jclouds.ohai.*;version="${project.version}";-noimport:=true ================================================ FILE: apis/chef/pom.xml ================================================ 4.0.0 org.apache.jclouds jclouds-project 2.7.1-SNAPSHOT ../../project/pom.xml org.apache.jclouds.api chef jclouds Chef api jclouds components to access Chef http://localhost:4000 chef-webui ${user.home}/.chef/webui.pem org.apache.jclouds jclouds-core ${project.version} org.apache.jclouds jclouds-core ${project.version} test-jar test org.apache.jclouds jclouds-scriptbuilder ${project.version} org.apache.jclouds jclouds-scriptbuilder ${project.version} test-jar test org.apache.jclouds jclouds-blobstore ${project.version} true org.apache.jclouds.driver jclouds-slf4j ${project.version} test ch.qos.logback logback-classic test com.google.auto.service auto-service true live org.apache.maven.plugins maven-surefire-plugin integration integration-test test ${test.chef.endpoint} ${test.chef.api-version} ${test.chef.build-version} ${test.chef.identity} ${test.chef.credential} ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/ChefApi.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef; import java.io.Closeable; import java.io.InputStream; import java.net.URI; import java.util.List; import java.util.Set; import jakarta.inject.Named; import jakarta.ws.rs.Consumes; import jakarta.ws.rs.DELETE; import jakarta.ws.rs.GET; import jakarta.ws.rs.POST; import jakarta.ws.rs.PUT; import jakarta.ws.rs.Path; import jakarta.ws.rs.PathParam; import jakarta.ws.rs.Produces; import jakarta.ws.rs.core.MediaType; import org.jclouds.Constants; import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404; import org.jclouds.Fallbacks.NullOnNotFoundOr404; import org.jclouds.Fallbacks.VoidOnNotFoundOr404; import org.jclouds.chef.binders.BindChecksumsToJsonPayload; import org.jclouds.chef.binders.BindCreateClientOptionsToJsonPayload; import org.jclouds.chef.binders.BindGenerateKeyForClientToJsonPayload; import org.jclouds.chef.binders.DatabagItemId; import org.jclouds.chef.binders.EnvironmentName; import org.jclouds.chef.binders.NodeName; import org.jclouds.chef.binders.RoleName; import org.jclouds.chef.domain.Client; import org.jclouds.chef.domain.CookbookDefinition; import org.jclouds.chef.domain.CookbookVersion; import org.jclouds.chef.domain.DatabagItem; import org.jclouds.chef.domain.Environment; import org.jclouds.chef.domain.Node; import org.jclouds.chef.domain.Resource; import org.jclouds.chef.domain.Role; import org.jclouds.chef.domain.Sandbox; import org.jclouds.chef.domain.SearchResult; import org.jclouds.chef.domain.UploadSandbox; import org.jclouds.chef.features.OrganizationApi; import org.jclouds.chef.filters.SignedHeaderAuth; import org.jclouds.chef.functions.ParseCookbookDefinitionFromJson; import org.jclouds.chef.functions.ParseCookbookDefinitionListFromJson; import org.jclouds.chef.functions.ParseCookbookNamesFromJson; import org.jclouds.chef.functions.ParseCookbookVersionsFromJson; import org.jclouds.chef.functions.ParseKeySetFromJson; import org.jclouds.chef.functions.ParseSearchClientsFromJson; import org.jclouds.chef.functions.ParseSearchDatabagFromJson; import org.jclouds.chef.functions.ParseSearchEnvironmentsFromJson; import org.jclouds.chef.functions.ParseSearchNodesFromJson; import org.jclouds.chef.functions.ParseSearchRolesFromJson; import org.jclouds.chef.functions.UriForResource; import org.jclouds.chef.options.CreateClientOptions; import org.jclouds.chef.options.SearchOptions; import org.jclouds.io.Payload; import org.jclouds.rest.annotations.BinderParam; import org.jclouds.rest.annotations.Delegate; import org.jclouds.rest.annotations.EndpointParam; import org.jclouds.rest.annotations.Fallback; import org.jclouds.rest.annotations.Headers; import org.jclouds.rest.annotations.MapBinder; import org.jclouds.rest.annotations.ParamParser; import org.jclouds.rest.annotations.PayloadParam; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.ResponseParser; import org.jclouds.rest.annotations.SelectJson; import org.jclouds.rest.annotations.SinceApiVersion; import org.jclouds.rest.annotations.SkipEncoding; import org.jclouds.rest.annotations.WrapWith; import org.jclouds.rest.binders.BindToJsonPayload; import com.google.common.base.Optional; import com.google.inject.Provides; /** * Provides synchronous access to Chef. */ @RequestFilters(SignedHeaderAuth.class) @Headers(keys = "X-Chef-Version", values = "{" + Constants.PROPERTY_API_VERSION + "}") @Consumes(MediaType.APPLICATION_JSON) public interface ChefApi extends Closeable { /** * Provides access to high level Chef features. */ @Provides ChefService chefService(); /** * Provides access to the organization, user and group management endpoints. */ @Delegate Optional organizationApi(); // Clients /** * Lists the names of the existing clients. * * @return The names of the existing clients. */ @Named("client:list") @GET @Path("/clients") @ResponseParser(ParseKeySetFromJson.class) @Fallback(EmptySetOnNotFoundOr404.class) Set listClients(); /** * Gets the details of existing client. * * @param clientName The name of the client to get. * @return The details of the given client. */ @Named("client:get") @GET @Path("/clients/{clientname}") @Fallback(NullOnNotFoundOr404.class) Client getClient(@PathParam("clientname") String clientName); /** * Creates a new client. * * @param clientName The name of the new client * @return The client with the generated private key. This key should be * stored so client can be properly authenticated . */ @Named("client:create") @POST @Path("/clients") @MapBinder(BindToJsonPayload.class) Client createClient(@PayloadParam("name") String clientName); /** * Creates a new client with custom options. * * @param clientName The name of the new client * @param options The options to customize the client creation. * @return The client with the generated private key. This key should be * stored so client can be properly authenticated . */ @Named("client:create") @POST @Path("/clients") @MapBinder(BindCreateClientOptionsToJsonPayload.class) Client createClient(@PayloadParam("name") String clientName, CreateClientOptions options); /** * Generates a new key-pair for this client, and return the new private key in * the response body. * * @param clientName The name of the client. * @return The details of the client with the new private key. */ @Named("client:generatekey") @PUT @Path("/clients/{clientname}") Client generateKeyForClient( @PathParam("clientname") @BinderParam(BindGenerateKeyForClientToJsonPayload.class) String clientName); /** * Deletes the given client. * * @param clientName The name of the client to delete. * @return The deleted client. */ @Named("client:delete") @DELETE @Path("/clients/{clientname}") @Fallback(NullOnNotFoundOr404.class) Client deleteClient(@PathParam("clientname") String clientName); // Cookbooks /** * Lists the names of the existing cookbooks. * * @return The names of the exsisting cookbooks. */ @Named("cookbook:list") @GET @Path("/cookbooks") @ResponseParser(ParseCookbookNamesFromJson.class) @Fallback(EmptySetOnNotFoundOr404.class) Set listCookbooks(); /** * Lists the cookbooks that are available in the given environment. * * @param environmentName The name of the environment to get the cookbooks * from. * @return The definitions of the cookbooks (name, URL and versions) available in * the given environment. */ @SinceApiVersion("0.10.0") @Named("cookbook:list") @GET @ResponseParser(ParseCookbookDefinitionListFromJson.class) @Path("/environments/{environmentname}/cookbooks") @Fallback(EmptySetOnNotFoundOr404.class) Set listCookbooksInEnvironment(@PathParam("environmentname") String environmentName); /** * Lists the cookbooks that are available in the given environment, limiting * the number of versions returned for each cookbook. * * @param environmentName The name of the environment to get the cookbooks * from. * @param numVersions The number of cookbook versions to include in the * response, where n is the number of cookbook versions. * @return The definitions of the cookbooks (name, URL and versions) available in * the given environment. */ @SinceApiVersion("0.10.0") @Named("cookbook:list") @GET @ResponseParser(ParseCookbookDefinitionListFromJson.class) @Path("/environments/{environmentname}/cookbooks?num_versions={numversions}") @Fallback(EmptySetOnNotFoundOr404.class) Set listCookbooksInEnvironment(@PathParam("environmentname") String environmentName, @PathParam("numversions") String numVersions); /** * Lists the available versions of the given cookbook. * * @param cookbookName The name of the cookbook. * @return The available versions of the given cookbook. */ @Named("cookbook:versions") @GET @Path("/cookbooks/{cookbookname}") @ResponseParser(ParseCookbookVersionsFromJson.class) @Fallback(EmptySetOnNotFoundOr404.class) Set listVersionsOfCookbook(@PathParam("cookbookname") String cookbookName); /** * Gets the details of the given cookbook, with the links to each resource * such as recipe files, attributes, etc. * * @param cookbookName The name of the cookbook. * @param version The version of the cookbook to get. * @return The details of the given cookbook. */ @Named("cookbook:get") @GET @Path("/cookbooks/{cookbookname}/{version}") @Fallback(NullOnNotFoundOr404.class) CookbookVersion getCookbook(@PathParam("cookbookname") String cookbookName, @PathParam("version") String version); /** * Gets the definition of the cookbook in the given environment. * * @param environmentName The name of the environment. * @param cookbookName The name of the cookbook. * @return The definition of the cookbook (URL and versions) of the cookbook * in the given environment. */ @SinceApiVersion("0.10.0") @Named("environment:cookbook") @GET @ResponseParser(ParseCookbookDefinitionFromJson.class) @Path("/environments/{environmentname}/cookbooks/{cookbookname}") CookbookDefinition getCookbookInEnvironment(@PathParam("environmentname") String environmentName, @PathParam("cookbookname") String cookbookName); /** * Gets the definition of the cookbook in the given environment. * * @param environmentName The name of the environment. * @param cookbookName The name of the cookbook. * @param numVersions The number of cookbook versions to include in the * response, where n is the number of cookbook versions. * @return The definition of the cookbook (URL and versions) of the cookbook * in the given environment. */ @SinceApiVersion("0.10.0") @Named("environment:cookbook") @GET @ResponseParser(ParseCookbookDefinitionFromJson.class) @Path("/environments/{environmentname}/cookbooks/{cookbookname}?num_versions={numversions}") CookbookDefinition getCookbookInEnvironment(@PathParam("environmentname") String environmentName, @PathParam("cookbookname") String cookbookName, @PathParam("numversions") String numVersions); /** * Lists the names of the recipes in the given environment. * * @param environmentName The name of the environment. * @return The names of the recipes in the given environment. */ @SinceApiVersion("0.10.0") @Named("environment:recipelist") @GET @Path("/environments/{environmentname}/recipes") @Fallback(EmptySetOnNotFoundOr404.class) Set listRecipesInEnvironment(@PathParam("environmentname") String environmentName); /** * Creates or updates the given cookbook. * * @param cookbookName The name of the cookbook to create or update. * @param version The version of the cookbook to create or update. * @param cookbook The contents of the cookbook to create or update. * @return The details of the created or updated cookbook. */ @Named("cookbook:update") @PUT @Path("/cookbooks/{cookbookname}/{version}") CookbookVersion updateCookbook(@PathParam("cookbookname") String cookbookName, @PathParam("version") String version, @BinderParam(BindToJsonPayload.class) CookbookVersion cookbook); /** * Deletes the given cookbook. * * @param cookbookName The name of the cookbook to delete. * @param version The version of the cookbook to delete. * @return The details of the deleted cookbook. */ @Named("cookbook:delete") @DELETE @Path("/cookbooks/{cookbookname}/{version}") @Fallback(NullOnNotFoundOr404.class) CookbookVersion deleteCookbook(@PathParam("cookbookname") String cookbookName, @PathParam("version") String version); // Data bags /** * Lists the names of the existing data bags. * * @return The names of the existing data bags. */ @Named("databag:list") @GET @Path("/data") @ResponseParser(ParseKeySetFromJson.class) @Fallback(EmptySetOnNotFoundOr404.class) Set listDatabags(); /** * Creates a new data bag. * * @param databagName The name for the new data bag. */ @Named("databag:create") @POST @Path("/data") void createDatabag(@WrapWith("name") String databagName); /** * Deletes a data bag, including its items. * * @param databagName The name of the data bag to delete. */ @Named("databag:delete") @DELETE @Path("/data/{name}") @Fallback(VoidOnNotFoundOr404.class) void deleteDatabag(@PathParam("name") String databagName); /** * Lists the names of the items in a data bag. * * @param databagName The name of the data bag. * @return The names of the items in the given data bag. */ @Named("databag:listitems") @GET @Path("/data/{name}") @ResponseParser(ParseKeySetFromJson.class) @Fallback(EmptySetOnNotFoundOr404.class) Set listDatabagItems(@PathParam("name") String databagName); /** * Gets an item in a data bag. * * @param databagName The name of the data bag. * @param databagItemId The identifier of the item to get. * @return The details of the item in the given data bag. */ @Named("databag:getitem") @GET @Path("/data/{databagName}/{databagItemId}") @Fallback(NullOnNotFoundOr404.class) DatabagItem getDatabagItem(@PathParam("databagName") String databagName, @PathParam("databagItemId") String databagItemId); /** * Adds an item in a data bag. * * @param databagName The name of the data bag. * @param databagItem item to add to the data bag. * @return The item just added to the data bag. */ @Named("databag:createitem") @POST @Path("/data/{databagName}") DatabagItem createDatabagItem(@PathParam("databagName") String databagName, @BinderParam(BindToJsonPayload.class) DatabagItem databagItem); /** * Updates an item in a data bag. * * @param databagName The name of the data bag. * @param item The new contents for the item in the data bag. * @return The details for the updated item in the data bag. */ @Named("databag:updateitem") @PUT @Path("/data/{databagName}/{databagItemId}") DatabagItem updateDatabagItem( @PathParam("databagName") String databagName, @PathParam("databagItemId") @ParamParser(DatabagItemId.class) @BinderParam(BindToJsonPayload.class) DatabagItem item); /** * Deletes an item from a data bag. * * @param databagName The name of the data bag. * @param databagItemId The identifier of the item to delete. * @return The item deleted from the data bag. */ @Named("databag:deleteitem") @DELETE @Path("/data/{databagName}/{databagItemId}") @Fallback(NullOnNotFoundOr404.class) @SelectJson("raw_data") DatabagItem deleteDatabagItem(@PathParam("databagName") String databagName, @PathParam("databagItemId") String databagItemId); // Environments /** * Lists the names of the existing environments. * * @return The names of the existing environments. */ @SinceApiVersion("0.10.0") @Named("environment:list") @GET @Path("/environments") @ResponseParser(ParseKeySetFromJson.class) @Fallback(EmptySetOnNotFoundOr404.class) Set listEnvironments(); /** * Gets the details of an existing environment. * * @param environmentName The name of the environment to get. * @return The details of the given environment. */ @SinceApiVersion("0.10.0") @Named("environment:get") @GET @Path("/environments/{environmentname}") @Fallback(NullOnNotFoundOr404.class) Environment getEnvironment(@PathParam("environmentname") String environmentName); /** * Creates a new environment. * * @param environment The environment to create. */ @SinceApiVersion("0.10.0") @Named("environment:create") @POST @Path("/environments") void createEnvironment(@BinderParam(BindToJsonPayload.class) Environment environment); /** * Updates the given environment. * * @param environment The new details for the environment. * @return The details of the updated environment. */ @SinceApiVersion("0.10.0") @Named("environment:update") @PUT @Path("/environments/{environmentname}") Environment updateEnvironment( @PathParam("environmentname") @ParamParser(EnvironmentName.class) @BinderParam(BindToJsonPayload.class) Environment environment); /** * Deletes the given environment. * * @param environmentName The name of the environment to delete. * @return The details of the deleted environment. */ @SinceApiVersion("0.10.0") @Named("environment:delete") @DELETE @Path("/environments/{environmentname}") @Fallback(NullOnNotFoundOr404.class) Environment deleteEnvironment(@PathParam("environmentname") String environmentName); // Nodes /** * Lists the names of the existing nodes. * * @return The names of the existing nodes. */ @Named("node:list") @GET @Path("/nodes") @ResponseParser(ParseKeySetFromJson.class) @Fallback(EmptySetOnNotFoundOr404.class) Set listNodes(); /** * Lists the names of the nodes in the given environment. * * @param environmentName The name of the environment. * @return The names of the existing nodes in the given environment. */ @SinceApiVersion("0.10.0") @Named("environment:nodelist") @GET @Path("/environments/{environmentname}/nodes") @ResponseParser(ParseKeySetFromJson.class) @Fallback(EmptySetOnNotFoundOr404.class) Set listNodesInEnvironment(@PathParam("environmentname") String environmentName); /** * Gets the details of the given node. * * @param nodeName The name of the node to get. * @return The details of the given node. */ @Named("node:get") @GET @Path("/nodes/{nodename}") @Fallback(NullOnNotFoundOr404.class) Node getNode(@PathParam("nodename") String nodeName); /** * Creates a new node. * * @param node The details of the node to create. */ @Named("node:create") @POST @Path("/nodes") void createNode(@BinderParam(BindToJsonPayload.class) Node node); /** * Updates an existing node. * * @param node The new details for the node. * @return The details of the updated node. */ @Named("node:update") @PUT @Path("/nodes/{nodename}") Node updateNode(@PathParam("nodename") @ParamParser(NodeName.class) @BinderParam(BindToJsonPayload.class) Node node); /** * Deletes the given node. * * @param nodeName The name of the node to delete. * @return The details of the deleted node. */ @Named("node:delete") @DELETE @Path("/nodes/{nodename}") @Fallback(NullOnNotFoundOr404.class) Node deleteNode(@PathParam("nodename") String nodeName); // Roles /** * Lists the names of the existing roles. * * @return The names of the existing roles. */ @Named("role:list") @GET @Path("/roles") @ResponseParser(ParseKeySetFromJson.class) @Fallback(EmptySetOnNotFoundOr404.class) Set listRoles(); /** * Gets the details of the given role. * * @param roleName The name of the role to get. * @return The details of the given role. */ @Named("role:get") @GET @Path("/roles/{rolename}") @Fallback(NullOnNotFoundOr404.class) Role getRole(@PathParam("rolename") String roleName); /** * Creates a new role. * * @param role The details for the new role. */ @Named("role:create") @POST @Path("/roles") void createRole(@BinderParam(BindToJsonPayload.class) Role role); /** * Updates the given role. * * @param role The new details for the role. * @return The details of the updated role. */ @Named("role:update") @PUT @Path("/roles/{rolename}") Role updateRole(@PathParam("rolename") @ParamParser(RoleName.class) @BinderParam(BindToJsonPayload.class) Role role); /** * Deletes the given role. * * @param roleName The name of the role to delete. * @return The details of the deleted role. */ @Named("role:delete") @DELETE @Path("/roles/{rolename}") @Fallback(NullOnNotFoundOr404.class) Role deleteRole(@PathParam("rolename") String roleName); // Sandboxes /** * Creates a new sandbox. *

* It accepts a list of checksums as input and returns the URLs against which * to PUT files that need to be uploaded. * * @param md5s The raw md5 sums. Uses {@code Bytes.asList()} and * {@code Bytes.toByteArray()} as necessary * @return The upload sandbox with the URLs against which to PUT files that * need to be uploaded. */ @Named("sandbox:upload") @POST @Path("/sandboxes") UploadSandbox createUploadSandboxForChecksums(@BinderParam(BindChecksumsToJsonPayload.class) Set> md5s); /** * Uploads the given content to the sandbox at the given URI. *

* The URI must be obtained, after uploading a sandbox, from the * {@link UploadSandbox#getUri()}. * * @param location The URI where the upload must be performed. * @param content The contents to upload. */ @Named("content:upload") @PUT @Produces("application/x-binary") void uploadContent(@EndpointParam URI location, Payload content); /** * Gets the contents of the given resource. * * @param resource The resource to get. * @return An input stream for the content of the requested resource. */ @Named("content:get") @GET @Fallback(NullOnNotFoundOr404.class) @SkipEncoding({ '+', ' ', '/', '=', ':', ';' }) InputStream getResourceContents(@EndpointParam(parser = UriForResource.class) Resource resource); /** * Confirms if the sandbox is completed or not. *

* This method should be used after uploading contents to the sandbox. * * @param id The id of the sandbox to commit. * @param isCompleted Flag to set if the sandbox is completed or not. * @return The details of the sandbox. */ @Named("sandbox:commit") @PUT @Path("/sandboxes/{id}") Sandbox commitSandbox(@PathParam("id") String id, @WrapWith("is_completed") boolean isCompleted); // Search /** * Lists the names of the available search indexes. *

* By default, the "role", "node" and "api" indexes will always be available. *

* Note that the search indexes may lag behind the most current data by at * least 10 seconds at any given time - so if you need to write data and * immediately query it, you likely need to produce an artificial delay (or * simply retry until the data is available). * * @return The names of the available search indexes. */ @Named("search:indexes") @GET @Path("/search") @ResponseParser(ParseKeySetFromJson.class) @Fallback(EmptySetOnNotFoundOr404.class) Set listSearchIndexes(); /** * Searches all clients. *

* Note that without any request parameters this will return all of the data * within the index. * * @return The response contains the total number of rows that matched the * request, the position this result set returns (useful for paging) * and the rows themselves. */ @Named("search:clients") @GET @Path("/search/client") @ResponseParser(ParseSearchClientsFromJson.class) SearchResult searchClients(); /** * Searches all clients that match the given options. * * @return The response contains the total number of rows that matched the * request, the position this result set returns (useful for paging) * and the rows themselves. */ @Named("search:clients") @GET @Path("/search/client") @ResponseParser(ParseSearchClientsFromJson.class) SearchResult searchClients(SearchOptions options); /** * Searches all items in a data bag. *

* Note that without any request parameters this will return all of the data * within the index. * * @return The response contains the total number of rows that matched the * request, the position this result set returns (useful for paging) * and the rows themselves. */ @Named("search:databag") @GET @Path("/search/{databagName}") @ResponseParser(ParseSearchDatabagFromJson.class) SearchResult searchDatabagItems(@PathParam("databagName") String databagName); /** * Searches all items in a data bag that match the given options. * * @return The response contains the total number of rows that matched the * request, the position this result set returns (useful for paging) * and the rows themselves. */ @Named("search:databag") @GET @Path("/search/{databagName}") @ResponseParser(ParseSearchDatabagFromJson.class) SearchResult searchDatabagItems(@PathParam("databagName") String databagName, SearchOptions options); /** * Searches all environments. *

* Note that without any request parameters this will return all of the data * within the index. * * @return The response contains the total number of rows that matched the * request, the position this result set returns (useful for paging) * and the rows themselves. */ @SinceApiVersion("0.10.0") @Named("search:environments") @GET @Path("/search/environment") @ResponseParser(ParseSearchEnvironmentsFromJson.class) SearchResult searchEnvironments(); /** * Searches all environments that match the given options. * * @return The response contains the total number of rows that matched the * request, the position this result set returns (useful for paging) * and the rows themselves. */ @SinceApiVersion("0.10.0") @Named("search:environments") @GET @Path("/search/environment") @ResponseParser(ParseSearchEnvironmentsFromJson.class) SearchResult searchEnvironments(SearchOptions options); /** * Searches all nodes. *

* Note that without any request parameters this will return all of the data * within the index. * * @return The response contains the total number of rows that matched the * request, the position this result set returns (useful for paging) * and the rows themselves. */ @Named("search:nodes") @GET @Path("/search/node") @ResponseParser(ParseSearchNodesFromJson.class) SearchResult searchNodes(); /** * Searches all nodes that match the given options. * * @return The response contains the total number of rows that matched the * request, the position this result set returns (useful for paging) * and the rows themselves. */ @Named("search:nodes") @GET @Path("/search/node") @ResponseParser(ParseSearchNodesFromJson.class) SearchResult searchNodes(SearchOptions options); /** * Searches all roles. *

* Note that without any request parameters this will return all of the data * within the index. * * @return The response contains the total number of rows that matched the * request, the position this result set returns (useful for paging) * and the rows themselves. */ @Named("search:roles") @GET @Path("/search/role") @ResponseParser(ParseSearchRolesFromJson.class) SearchResult searchRoles(); /** * Searches all roles that match the given options. * * @return The response contains the total number of rows that matched the * request, the position this result set returns (useful for paging) * and the rows themselves. */ @Named("search:roles") @GET @Path("/search/role") @ResponseParser(ParseSearchRolesFromJson.class) SearchResult searchRoles(SearchOptions options); } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/ChefApiMetadata.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef; import static java.util.concurrent.TimeUnit.MINUTES; import static java.util.concurrent.TimeUnit.SECONDS; import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL; import static org.jclouds.Constants.PROPERTY_TIMEOUTS_PREFIX; import static org.jclouds.chef.config.ChefProperties.CHEF_BOOTSTRAP_DATABAG; import static org.jclouds.chef.config.ChefProperties.CHEF_UPDATE_GEMS; import static org.jclouds.chef.config.ChefProperties.CHEF_UPDATE_GEM_SYSTEM; import static org.jclouds.chef.config.ChefProperties.CHEF_USE_OMNIBUS; import java.net.URI; import java.util.Properties; import org.jclouds.apis.ApiMetadata; import org.jclouds.chef.config.ChefBootstrapModule; import org.jclouds.chef.config.ChefHttpApiModule; import org.jclouds.chef.config.ChefParserModule; import org.jclouds.ohai.config.JMXOhaiModule; import org.jclouds.rest.internal.BaseHttpApiMetadata; import com.google.auto.service.AutoService; import com.google.common.collect.ImmutableSet; import com.google.inject.Module; /** * Implementation of {@link ApiMetadata} for Chef. */ @AutoService(ApiMetadata.class) public class ChefApiMetadata extends BaseHttpApiMetadata { /** * The default Chef Server API version to use. */ public static final String DEFAULT_API_VERSION = "12.0.2"; @Override public Builder toBuilder() { return new Builder().fromApiMetadata(this); } public ChefApiMetadata() { this(new Builder()); } protected ChefApiMetadata(Builder builder) { super(builder); } public static Properties defaultProperties() { Properties properties = BaseHttpApiMetadata.defaultProperties(); properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "default", SECONDS.toMillis(30) + ""); properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "ChefApi.updateCookbook", MINUTES.toMillis(10) + ""); properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "ChefApi.createClient", MINUTES.toMillis(2) + ""); properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "ChefApi.generateKeyForClient", MINUTES.toMillis(2) + ""); properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "ChefApi.createNode", MINUTES.toMillis(2) + ""); properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "ChefApi.updateNode", MINUTES.toMillis(10) + ""); properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "ChefApi.createRole", MINUTES.toMillis(2) + ""); properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "ChefApi.updateRole", MINUTES.toMillis(10) + ""); properties.setProperty(PROPERTY_TIMEOUTS_PREFIX + "ChefApi.createEnvironment", MINUTES.toMillis(2) + ""); properties.setProperty(PROPERTY_SESSION_INTERVAL, "1"); properties.setProperty(CHEF_BOOTSTRAP_DATABAG, "bootstrap"); properties.setProperty(CHEF_UPDATE_GEM_SYSTEM, "false"); properties.setProperty(CHEF_UPDATE_GEMS, "false"); properties.setProperty(CHEF_USE_OMNIBUS, "true"); return properties; } public static class Builder extends BaseHttpApiMetadata.Builder { protected Builder() { id("chef") .name("Chef Api") .identityName("User") .credentialName("Certificate") .version(DEFAULT_API_VERSION) .documentation(URI.create("https://docs.chef.io/api_chef_server.html")) .defaultEndpoint("http://localhost:4000") .defaultProperties(ChefApiMetadata.defaultProperties()) .defaultModules( ImmutableSet.> of(ChefHttpApiModule.class, ChefParserModule.class, ChefBootstrapModule.class, JMXOhaiModule.class)); } @Override public ChefApiMetadata build() { return new ChefApiMetadata(this); } @Override protected Builder self() { return this; } } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/ChefService.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef; import java.io.IOException; import java.io.InputStream; import java.util.concurrent.ExecutorService; import org.jclouds.chef.config.ChefProperties; import org.jclouds.chef.domain.BootstrapConfig; import org.jclouds.chef.domain.Client; import org.jclouds.chef.domain.CookbookVersion; import org.jclouds.chef.domain.Environment; import org.jclouds.chef.domain.Node; import org.jclouds.chef.internal.BaseChefService; import org.jclouds.chef.util.ChefUtils; import org.jclouds.javax.annotation.Nullable; import org.jclouds.ohai.config.OhaiModule; import org.jclouds.rest.annotations.SinceApiVersion; import org.jclouds.scriptbuilder.domain.Statement; import com.google.inject.ImplementedBy; /** * Provides high level Chef operations. */ @ImplementedBy(BaseChefService.class) public interface ChefService { // Crypto /** * Encrypts the given input stream. * * @param input The input stream to encrypt. * @return The encrypted bytes for the given input stream. * @throws IOException If there is an error reading from the input stream. */ byte[] encrypt(InputStream input) throws IOException; /** * Decrypts the given input stream. * * @param input The input stream to decrypt. * @return The decrypted bytes for the given input stream. * @throws IOException If there is an error reading from the input stream. */ byte[] decrypt(InputStream input) throws IOException; // Bootstrap /** * Creates all steps necessary to bootstrap the node. * * @param group corresponds to a configured * {@link ChefProperties#CHEF_BOOTSTRAP_DATABAG} data bag where * run_list and other information are stored. * @return The script used to bootstrap the node. */ Statement createBootstrapScriptForGroup(String group); /** * Creates all steps necessary to bootstrap the node. * * @param group corresponds to a configured * {@link ChefProperties#CHEF_BOOTSTRAP_DATABAG} data bag where * run_list and other information are stored. * @param nodeName The name of the node to create. * @return The script used to bootstrap the node. */ Statement createBootstrapScriptForGroup(String group, @Nullable String nodeName); /** * Configures how the nodes of a certain group will be bootstrapped * * @param group The group where the given bootstrap configuration will be * applied. * @param bootstrapConfig The configuration to be applied to the nodes in the * group. */ void updateBootstrapConfigForGroup(String group, BootstrapConfig bootstrapConfig); /** * Gets the bootstrap configuration for a given group. * * @param group The name of the group. * @return The bootstrap configuration for the given group. */ BootstrapConfig getBootstrapConfigForGroup(String group); // Nodes / Clients /** * Creates a new node and populates the automatic attributes. * * @param nodeName The name of the node to create. * @param runList The run list for the created node. * @return The created node with the automatic attributes populated. * @see OhaiModule * @see ChefUtils#ohaiAutomaticAttributeBinder(com.google.inject.Binder) */ Node createNodeAndPopulateAutomaticAttributes(String nodeName, Iterable runList); /** * Updates and populate the automatic attributes of the given node. * * @param nodeName The node to update. */ void updateAutomaticAttributesOnNode(String nodeName); /** * Removes the nodes and clients that have been inactive for a given amount of * time. * * @param prefix The prefix for the nodes and clients to delete. * @param secondsStale The seconds of inactivity to consider a node and * client obsolete. */ void cleanupStaleNodesAndClients(String prefix, int secondsStale); /** * Deletes the given nodes. * * @param names The names of the nodes to delete. */ void deleteAllNodesInList(Iterable names); /** * Deletes the given clients. * * @param names The names of the client to delete. */ void deleteAllClientsInList(Iterable names); /** * Lists the details of all existing nodes. * * @return The details of all existing nodes. */ Iterable listNodes(); /** * Lists the details of all existing nodes, executing concurrently using the executorService. * * @return The details of all existing nodes. */ Iterable listNodes(ExecutorService executorService); /** * Lists the details of all existing nodes in the given environment. * * @param environmentName The name fo the environment. * @return The details of all existing nodes in the given environment. */ @SinceApiVersion("0.10.0") Iterable listNodesInEnvironment(String environmentName); /** * Lists the details of all existing nodes in the given environment, using the ExecutorService to paralleling the execution. * * @param executorService The thread pool used in this operation * @param environmentName The name fo the environment. * @return The details of all existing nodes in the given environment. */ @SinceApiVersion("0.10.0") Iterable listNodesInEnvironment(String environmentName, ExecutorService executorService); /** * Lists the details of all existing clients. * * @return The details of all existing clients. */ Iterable listClients(); /** * Lists the details of all existing clients, but executing concurrently using the threads available in the ExecutorService. * * @return The details of all existing clients. */ Iterable listClients(ExecutorService executorService); /** * Lists the details of all existing cookbooks. * * @return The details of all existing cookbooks. */ Iterable listCookbookVersions(); /** * Lists the details of all existing cookbooks. This method is executed concurrently, using the threads available in the ExecutorService. * * @return The details of all existing cookbooks. */ Iterable listCookbookVersions(ExecutorService executorService); /** * Lists the details of all existing cookbooks in an environment. * * @param environmentName The environment name. * @return The details of all existing cookbooks in an environment. */ Iterable listCookbookVersionsInEnvironment(String environmentName); /** * Lists the details of all existing cookbooks in an environment. * @param executorService The thread pool to do the concurrent execution. * @param environmentName The environment name. * @return The details of all existing cookbooks in an environment. */ Iterable listCookbookVersionsInEnvironment(String environmentName, ExecutorService executorService); /** * Lists the details of all existing cookbooks in an environment * limiting number of versions. * * @param environmentName The environment name. * @param numVersions The number of cookbook versions to include. * Use 'all' to return all cookbook versions. * @return The details of all existing cookbooks in environment. */ Iterable listCookbookVersionsInEnvironment(String environmentName, String numVersions); /** * Lists the details of all existing cookbooks in an environment * limiting number of versions. * * @param executorService The executorService used to do this operation concurrently. * @param environmentName The environment name. * @param numVersions The number of cookbook versions to include. * Use 'all' to return all cookbook versions. * @return The details of all existing cookbooks in environment. */ Iterable listCookbookVersionsInEnvironment(String environmentName, String numVersions, ExecutorService executorService); /** * Lists the details of all existing environments. * * @return The details of all existing environments. */ @SinceApiVersion("0.10.0") Iterable listEnvironments(); } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/binders/BindChecksumsToJsonPayload.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.binders; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.io.BaseEncoding.base16; import static com.google.common.primitives.Bytes.toArray; import java.util.List; import java.util.Set; import jakarta.inject.Singleton; import jakarta.ws.rs.core.MediaType; import org.jclouds.http.HttpRequest; import org.jclouds.rest.binders.BindToStringPayload; @Singleton public class BindChecksumsToJsonPayload extends BindToStringPayload { @SuppressWarnings("unchecked") public HttpRequest bindToRequest(HttpRequest request, Object input) { checkArgument(checkNotNull(input, "input") instanceof Set, "this binder is only valid for Set!"); Set> md5s = (Set>) input; StringBuilder builder = new StringBuilder(); builder.append("{\"checksums\":{"); for (List md5 : md5s) builder.append(String.format("\"%s\":null,", base16().lowerCase().encode(toArray(md5)))); builder.deleteCharAt(builder.length() - 1); builder.append("}}"); super.bindToRequest(request, builder.toString()); request.getPayload().getContentMetadata().setContentType(MediaType.APPLICATION_JSON); return request; } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/binders/BindCreateClientOptionsToJsonPayload.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.binders; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; import java.util.Map; import jakarta.inject.Inject; import org.jclouds.chef.options.CreateClientOptions; import org.jclouds.http.HttpRequest; import org.jclouds.json.Json; import org.jclouds.rest.binders.BindToJsonPayload; import org.jclouds.rest.internal.GeneratedHttpRequest; import com.google.common.base.Predicates; import com.google.common.collect.Iterables; /** * Bind the parameters of a {@link CreateClientOptions} to the payload. */ public class BindCreateClientOptionsToJsonPayload extends BindToJsonPayload { @Inject public BindCreateClientOptionsToJsonPayload(Json jsonBinder) { super(jsonBinder); } @Override public R bindToRequest(R request, Map postParams) { checkArgument(checkNotNull(request, "request") instanceof GeneratedHttpRequest, "this binder is only valid for GeneratedHttpRequests"); GeneratedHttpRequest gRequest = (GeneratedHttpRequest) request; checkState(gRequest.getInvocation().getArgs() != null, "args should be initialized at this point"); String name = checkNotNull(postParams.remove("name"), "name").toString(); CreateClientOptions options = (CreateClientOptions) Iterables.find(gRequest.getInvocation().getArgs(), Predicates.instanceOf(CreateClientOptions.class)); return bindToRequest(request, new CreateClientParams(name, options)); } @SuppressWarnings("unused") private static class CreateClientParams { private String name; private boolean admin; public CreateClientParams(String name, CreateClientOptions options) { this.name = name; this.admin = options.isAdmin(); } } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/binders/BindGenerateKeyForClientToJsonPayload.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.binders; import jakarta.inject.Singleton; import jakarta.ws.rs.core.MediaType; import org.jclouds.http.HttpRequest; import org.jclouds.rest.binders.BindToStringPayload; @Singleton public class BindGenerateKeyForClientToJsonPayload extends BindToStringPayload { @Override public R bindToRequest(R request, Object payload) { super.bindToRequest(request, String.format("{\"name\":\"%s\", \"private_key\": true}", payload)); request.getPayload().getContentMetadata().setContentType(MediaType.APPLICATION_JSON); return request; } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/binders/BindGroupToUpdateRequestJsonPayload.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.binders; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import java.util.Set; import jakarta.inject.Inject; import jakarta.inject.Singleton; import org.jclouds.chef.domain.Group; import org.jclouds.http.HttpRequest; import org.jclouds.json.Json; import org.jclouds.rest.binders.BindToJsonPayload; /** * Binds a group to the payload expected for the Put method in the Enterprise Chef * Api. */ @Singleton public class BindGroupToUpdateRequestJsonPayload extends BindToJsonPayload { @Inject public BindGroupToUpdateRequestJsonPayload(Json jsonBinder) { super(jsonBinder); } @Override public R bindToRequest(R request, Object payload) { checkArgument(checkNotNull(payload, "payload") instanceof Group, "this binder is only valid for Group objects"); GroupUpdateRequest updateGroup = new GroupUpdateRequest((Group) payload); return super.bindToRequest(request, updateGroup); } @SuppressWarnings("unused") private static class GroupUpdateRequest { private String name; private String groupname; private String orgname; private ActorConfiguration actors; public GroupUpdateRequest(Group group) { this.name = group.getName(); this.groupname = group.getGroupname(); this.orgname = group.getOrgname(); this.actors = new ActorConfiguration(group); } } @SuppressWarnings("unused") private static class ActorConfiguration { private Set clients; private Set groups; private Set users; public ActorConfiguration(Group group) { this.clients = group.getClients(); this.groups = group.getGroups(); this.users = group.getUsers(); } } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/binders/DatabagItemId.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.binders; import jakarta.inject.Singleton; import org.jclouds.chef.domain.DatabagItem; import com.google.common.base.Function; @Singleton public class DatabagItemId implements Function { public String apply(Object from) { return ((DatabagItem) from).getId(); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/binders/EnvironmentName.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.binders; import com.google.common.base.Function; import org.jclouds.chef.domain.Environment; import jakarta.inject.Singleton; @Singleton public class EnvironmentName implements Function { @Override public String apply(Object input) { return ((Environment) input).getName(); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/binders/GroupName.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.binders; import static com.google.common.base.Preconditions.checkNotNull; import jakarta.inject.Singleton; import org.jclouds.chef.domain.Group; import com.google.common.base.Function; /** * Gets the name of a group. */ @Singleton public class GroupName implements Function { @Override public String apply(Object from) { return ((Group) checkNotNull(from, "from")).getGroupname(); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/binders/NodeName.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.binders; import jakarta.inject.Singleton; import org.jclouds.chef.domain.Node; import com.google.common.base.Function; @Singleton public class NodeName implements Function { public String apply(Object from) { return ((Node) from).getName(); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/binders/RoleName.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.binders; import jakarta.inject.Singleton; import org.jclouds.chef.domain.Role; import com.google.common.base.Function; @Singleton public class RoleName implements Function { public String apply(Object from) { return ((Role) from).getName(); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/config/ChefBootstrapModule.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.config; import static org.jclouds.chef.config.ChefProperties.CHEF_GEM_SYSTEM_VERSION; import static org.jclouds.chef.config.ChefProperties.CHEF_UPDATE_GEMS; import static org.jclouds.chef.config.ChefProperties.CHEF_UPDATE_GEM_SYSTEM; import static org.jclouds.chef.config.ChefProperties.CHEF_USE_OMNIBUS; import static org.jclouds.chef.config.ChefProperties.CHEF_VERSION; import jakarta.inject.Named; import jakarta.inject.Singleton; import org.jclouds.scriptbuilder.domain.Statement; import org.jclouds.scriptbuilder.domain.StatementList; import org.jclouds.scriptbuilder.statements.chef.InstallChefGems; import org.jclouds.scriptbuilder.statements.chef.InstallChefUsingOmnibus; import org.jclouds.scriptbuilder.statements.ruby.InstallRuby; import org.jclouds.scriptbuilder.statements.ruby.InstallRubyGems; import com.google.common.base.Optional; import com.google.inject.AbstractModule; import com.google.inject.Inject; import com.google.inject.Provides; /** * Provides bootstrap configuration for nodes. */ public class ChefBootstrapModule extends AbstractModule { @Provides @Named("installChefGems") @Singleton final Statement installChefGems(BootstrapProperties bootstrapProperties) { InstallRubyGems installRubyGems = InstallRubyGems.builder() .version(bootstrapProperties.gemSystemVersion().orNull()) .updateSystem(bootstrapProperties.updateGemSystem(), bootstrapProperties.gemSystemVersion().orNull()) .updateExistingGems(bootstrapProperties.updateGems()) // .build(); Statement installChef = InstallChefGems.builder().version(bootstrapProperties.chefVersion().orNull()).build(); return new StatementList(InstallRuby.builder().build(), installRubyGems, installChef); } @Provides @Named("installChefOmnibus") @Singleton final Statement installChefUsingOmnibus(BootstrapProperties bootstrapProperties) { return bootstrapProperties.chefVersion().isPresent() ? new InstallChefUsingOmnibus(bootstrapProperties.chefVersion().get()) : new InstallChefUsingOmnibus(); } @Provides @InstallChef @Singleton final Statement installChef(BootstrapProperties bootstrapProperties, @Named("installChefGems") Statement installChefGems, @Named("installChefOmnibus") Statement installChefOmnibus) { return bootstrapProperties.useOmnibus() ? installChefOmnibus : installChefGems; } @Singleton private static class BootstrapProperties { @Named(CHEF_VERSION) @Inject(optional = true) private String chefVersionProperty; @Named(CHEF_GEM_SYSTEM_VERSION) @Inject(optional = true) private String gemSystemVersionProperty; @Named(CHEF_UPDATE_GEM_SYSTEM) @Inject private String updateGemSystemProeprty; @Named(CHEF_UPDATE_GEMS) @Inject private String updateGemsProperty; @Named(CHEF_USE_OMNIBUS) @Inject private String useOmnibus; public Optional chefVersion() { return Optional.fromNullable(chefVersionProperty); } public Optional gemSystemVersion() { return Optional.fromNullable(gemSystemVersionProperty); } public boolean updateGemSystem() { return Boolean.parseBoolean(updateGemSystemProeprty); } public boolean updateGems() { return Boolean.parseBoolean(updateGemsProperty); } public boolean useOmnibus() { return Boolean.parseBoolean(useOmnibus); } } @Override protected void configure() { } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/config/ChefHttpApiModule.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.config; import static com.google.common.base.Suppliers.compose; import static com.google.common.base.Suppliers.memoizeWithExpiration; import static com.google.common.base.Throwables.propagate; import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL; import static org.jclouds.chef.config.ChefProperties.CHEF_VALIDATOR_CREDENTIAL; import static org.jclouds.chef.config.ChefProperties.CHEF_VALIDATOR_NAME; import static org.jclouds.crypto.Pems.privateKeySpec; import java.io.IOException; import java.security.PrivateKey; import java.security.spec.InvalidKeySpecException; import java.util.concurrent.TimeUnit; import jakarta.inject.Inject; import jakarta.inject.Named; import jakarta.inject.Singleton; import org.jclouds.chef.ChefApi; import org.jclouds.chef.domain.BootstrapConfig; import org.jclouds.chef.domain.Client; import org.jclouds.chef.functions.BootstrapConfigForGroup; import org.jclouds.chef.functions.ClientForGroup; import org.jclouds.chef.handlers.ChefApiErrorRetryHandler; import org.jclouds.chef.handlers.ChefErrorHandler; import org.jclouds.crypto.Crypto; import org.jclouds.crypto.Pems; import org.jclouds.date.DateService; import org.jclouds.date.TimeStamp; import org.jclouds.domain.Credentials; import org.jclouds.http.HttpErrorHandler; import org.jclouds.http.HttpRetryHandler; import org.jclouds.http.annotation.ClientError; import org.jclouds.http.annotation.Redirection; import org.jclouds.http.annotation.ServerError; import org.jclouds.rest.ConfiguresHttpApi; import org.jclouds.rest.config.HttpApiModule; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Charsets; import com.google.common.base.Function; import com.google.common.base.Optional; import com.google.common.base.Supplier; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.io.ByteSource; import com.google.inject.ConfigurationException; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Provides; import com.google.inject.name.Names; /** * Configures the Chef connection. */ @ConfiguresHttpApi public class ChefHttpApiModule extends HttpApiModule { @Provides @TimeStamp protected final String guiceProvideTimeStamp(@TimeStamp Supplier cache) { return provideTimeStamp(cache); } protected String provideTimeStamp(@TimeStamp Supplier cache) { return cache.get(); } /** * borrowing concurrency code to ensure that caching takes place properly */ @Provides @TimeStamp final Supplier provideTimeStampCache(@Named(PROPERTY_SESSION_INTERVAL) long seconds, final DateService dateService) { return memoizeWithExpiration(new Supplier() { @Override public String get() { return dateService.iso8601SecondsDateFormat(); } }, seconds, TimeUnit.SECONDS); } // TODO: potentially change this @Provides @Singleton public final Supplier supplyKey(final LoadingCache keyCache, @org.jclouds.location.Provider final Supplier creds) { return compose(new Function() { @Override public PrivateKey apply(Credentials in) { return keyCache.getUnchecked(in); } }, creds); } @Provides @Singleton final LoadingCache privateKeyCache(PrivateKeyForCredentials loader) { // throw out the private key related to old credentials return CacheBuilder.newBuilder().maximumSize(2).build(loader); } /** * it is relatively expensive to extract a private key from a PEM. cache the * relationship between current credentials so that the private key is only * recalculated once. */ @VisibleForTesting @Singleton private static class PrivateKeyForCredentials extends CacheLoader { private final Crypto crypto; @Inject private PrivateKeyForCredentials(Crypto crypto) { this.crypto = crypto; } @Override public PrivateKey load(Credentials in) { try { return crypto.rsaKeyFactory().generatePrivate( privateKeySpec(ByteSource.wrap(in.credential.getBytes(Charsets.UTF_8)))); } catch (InvalidKeySpecException e) { throw propagate(e); } catch (IOException e) { throw propagate(e); } } } @Provides @Singleton @Validator public final Optional provideValidatorName(Injector injector) { // Named properties can not be injected as optional here, so let's use the // injector to bypass it Key key = Key.get(String.class, Names.named(CHEF_VALIDATOR_NAME)); try { return Optional. of(injector.getInstance(key)); } catch (ConfigurationException ex) { return Optional. absent(); } } @Provides @Singleton @Validator public final Optional provideValidatorCredential(Crypto crypto, Injector injector) throws InvalidKeySpecException, IOException { // Named properties can not be injected as optional here, so let's use the // injector to bypass it Key key = Key.get(String.class, Names.named(CHEF_VALIDATOR_CREDENTIAL)); try { String validatorCredential = injector.getInstance(key); PrivateKey validatorKey = crypto.rsaKeyFactory().generatePrivate( Pems.privateKeySpec(ByteSource.wrap(validatorCredential.getBytes(Charsets.UTF_8)))); return Optional. of(validatorKey); } catch (ConfigurationException ex) { return Optional. absent(); } } @Provides @Singleton final CacheLoader bootstrapConfigForGroup(BootstrapConfigForGroup bootstrapConfigForGroup) { return CacheLoader.from(bootstrapConfigForGroup); } @Provides @Singleton final CacheLoader groupToClient(ClientForGroup clientForGroup) { return CacheLoader.from(clientForGroup); } @Override protected void bindErrorHandlers() { bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(ChefErrorHandler.class); bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(ChefErrorHandler.class); bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(ChefErrorHandler.class); } @Override protected void bindRetryHandlers() { bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(ChefApiErrorRetryHandler.class); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/config/ChefParserModule.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.config; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkState; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.lang.reflect.Type; import java.security.PrivateKey; import java.security.PublicKey; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.security.spec.InvalidKeySpecException; import java.util.Map; import jakarta.inject.Inject; import jakarta.inject.Singleton; import org.jclouds.chef.domain.DatabagItem; import org.jclouds.crypto.Crypto; import org.jclouds.crypto.Pems; import org.jclouds.json.config.GsonModule.DateAdapter; import org.jclouds.json.config.GsonModule.Iso8601DateAdapter; import com.google.gson.internal.JsonReaderInternalAccess; import org.jclouds.json.internal.NullFilteringTypeAdapterFactories; import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.MapTypeAdapterFactory; import org.jclouds.json.internal.NullHackJsonLiteralAdapter; import com.google.common.base.Charsets; import com.google.common.base.Throwables; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; import com.google.common.io.ByteSource; import com.google.gson.Gson; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; import com.google.gson.JsonParseException; import com.google.gson.JsonSyntaxException; import com.google.gson.TypeAdapter; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonToken; import com.google.inject.AbstractModule; import com.google.inject.ImplementedBy; import com.google.inject.Provides; public class ChefParserModule extends AbstractModule { @ImplementedBy(PrivateKeyAdapterImpl.class) public interface PrivateKeyAdapter extends JsonDeserializer { } @Singleton public static class PrivateKeyAdapterImpl implements PrivateKeyAdapter { private final Crypto crypto; @Inject PrivateKeyAdapterImpl(Crypto crypto) { this.crypto = crypto; } @Override public PrivateKey deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { String keyText = json.getAsString().replaceAll("\\n", "\n"); try { return crypto.rsaKeyFactory().generatePrivate( Pems.privateKeySpec(ByteSource.wrap(keyText.getBytes(Charsets.UTF_8)))); } catch (UnsupportedEncodingException e) { Throwables.propagate(e); return null; } catch (InvalidKeySpecException e) { Throwables.propagate(e); return null; } catch (IOException e) { Throwables.propagate(e); return null; } } } @ImplementedBy(PublicKeyAdapterImpl.class) public interface PublicKeyAdapter extends JsonDeserializer { } @Singleton public static class PublicKeyAdapterImpl implements PublicKeyAdapter { private final Crypto crypto; @Inject PublicKeyAdapterImpl(Crypto crypto) { this.crypto = crypto; } @Override public PublicKey deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { String keyText = json.getAsString().replaceAll("\\n", "\n"); try { return crypto.rsaKeyFactory().generatePublic( Pems.publicKeySpec(ByteSource.wrap(keyText.getBytes(Charsets.UTF_8)))); } catch (UnsupportedEncodingException e) { Throwables.propagate(e); return null; } catch (InvalidKeySpecException e) { Throwables.propagate(e); return null; } catch (IOException e) { Throwables.propagate(e); return null; } } } @ImplementedBy(X509CertificateAdapterImpl.class) public interface X509CertificateAdapter extends JsonDeserializer { } @Singleton public static class X509CertificateAdapterImpl implements X509CertificateAdapter { private final Crypto crypto; @Inject X509CertificateAdapterImpl(Crypto crypto) { this.crypto = crypto; } @Override public X509Certificate deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { String keyText = json.getAsString().replaceAll("\\n", "\n"); try { return Pems.x509Certificate(ByteSource.wrap(keyText.getBytes(Charsets.UTF_8)), crypto.certFactory()); } catch (UnsupportedEncodingException e) { Throwables.propagate(e); return null; } catch (IOException e) { Throwables.propagate(e); return null; } catch (CertificateException e) { Throwables.propagate(e); return null; } } } /** * writes or reads the literal directly */ @Singleton public static class DataBagItemAdapter extends NullHackJsonLiteralAdapter { final Gson gson = new Gson(); @Override protected DatabagItem createJsonLiteralFromRawJson(String text) { IdHolder idHolder = gson.fromJson(text, IdHolder.class); checkState(idHolder.id != null, "databag item must be a json hash ex. {\"id\":\"item1\",\"my_key\":\"my_data\"}; was %s", text); text = text.replaceFirst(String.format("\\{\"id\"[ ]?:\"%s\",", idHolder.id), "{"); return new DatabagItem(idHolder.id, text); } @Override protected String toString(DatabagItem value) { String text = value.toString(); try { IdHolder idHolder = gson.fromJson(text, IdHolder.class); if (idHolder.id == null) { text = text.replaceFirst("\\{", String.format("{\"id\":\"%s\",", value.getId())); } else { checkArgument(value.getId().equals(idHolder.id), "incorrect id in databagItem text, should be %s: was %s", value.getId(), idHolder.id); } } catch (JsonSyntaxException e) { throw new IllegalArgumentException(e); } return text; } } private static class IdHolder { private String id; } private static final class KeepLastRepeatedKeyMapTypeAdapter extends NullFilteringTypeAdapterFactories.MapTypeAdapter { protected KeepLastRepeatedKeyMapTypeAdapter(TypeAdapter keyAdapter, TypeAdapter valueAdapter) { super(keyAdapter, valueAdapter); } @Override public Map read(JsonReader in) throws IOException { if (in.peek() == JsonToken.NULL) { in.nextNull(); return null; } Map result = Maps.newHashMap(); in.beginObject(); while (in.hasNext()) { JsonReaderInternalAccess.INSTANCE.promoteNameToValue(in); K name = keyAdapter.read(in); V value = valueAdapter.read(in); if (value != null) { // If there are repeated keys, overwrite them to only keep the // last one result.put(name, value); } } in.endObject(); return ImmutableMap.copyOf(result); } } public static class KeepLastRepeatedKeyMapTypeAdapterFactory extends MapTypeAdapterFactory { public KeepLastRepeatedKeyMapTypeAdapterFactory() { super(Map.class); } @SuppressWarnings("unchecked") @Override protected TypeAdapter newAdapter(TypeAdapter keyAdapter, TypeAdapter valueAdapter) { return (TypeAdapter) new KeepLastRepeatedKeyMapTypeAdapter(keyAdapter, valueAdapter); } } @Provides @Singleton public final Map provideCustomAdapterBindings(DataBagItemAdapter adapter, PrivateKeyAdapter privateAdapter, PublicKeyAdapter publicAdapter, X509CertificateAdapter certAdapter) { return ImmutableMap. of(DatabagItem.class, adapter, PrivateKey.class, privateAdapter, PublicKey.class, publicAdapter, X509Certificate.class, certAdapter); } @Override protected void configure() { bind(DateAdapter.class).to(Iso8601DateAdapter.class); bind(MapTypeAdapterFactory.class).to(KeepLastRepeatedKeyMapTypeAdapterFactory.class); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/config/ChefProperties.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.config; /** * Configuration properties and constants used in Chef connections. */ public final class ChefProperties { /** * The name of the Chef logger. */ public static final String CHEF_LOGGER = "jclouds.chef"; /** * Databag that holds chef bootstrap hints, should be a json ball in the * following format: *

* {"tag":{"run_list":["recipe[apache2]"]}} */ public static final String CHEF_BOOTSTRAP_DATABAG = "chef.bootstrap-databag"; /** * The name of the validator client used to allow nodes to autoregister in * the Chef server. *

* This property must be set prior to running the * {@link ChefService#createBootstrapScriptForGroup(String)} method. */ public static final String CHEF_VALIDATOR_NAME = "chef.validator-name"; /** * The credential of the validator client used to allow nodes to autoregister * in the Chef server. *

* This property must be set prior to running the * {@link ChefService#createBootstrapScriptForGroup(String)} method. */ public static final String CHEF_VALIDATOR_CREDENTIAL = "chef.validator-credential"; /** * The version of the Chef gem to install when bootstrapping nodes. *

* If this property is not set, by default the latest available Chef gem will * be installed. The values can be fixed versions such as '0.10.8' or * constrained values such as '>= 0.10.8'. *

* This property must be set prior to running the * {@link ChefService#createBootstrapScriptForGroup(String)} method. */ public static final String CHEF_VERSION = "chef.version"; /** * Boolean property. Default (false). *

* When bootstrapping a node, forces a gem system update before installing * the Chef gems. *

* This property must be set prior to running the * {@link ChefService#createBootstrapScriptForGroup(String)} method. */ public static final String CHEF_UPDATE_GEM_SYSTEM = "chef.update-gem-system"; /** * To be used in conjunction with {@link #CHEF_UPDATE_GEM_SYSTEM}. This * property will force the version of RubyGems to update the system to. *

* This property must be set prior to running the * {@link ChefService#createBootstrapScriptForGroup(String)} method. */ public static final String CHEF_GEM_SYSTEM_VERSION = "chef.gem-system-version"; /** * Boolean property. Default (false). *

* When bootstrapping a node, updates the existing gems before installing * Chef. *

* This property must be set prior to running the * {@link ChefService#createBootstrapScriptForGroup(String)} method. */ public static final String CHEF_UPDATE_GEMS = "chef.update-gems"; /** * Boolean property. Default (true). *

* When bootstrapping a node, install the Chef client using the Omnibus * installer. *

* This property must be set prior to running the * {@link ChefService#createBootstrapScriptForGroup(String)} method. */ public static final String CHEF_USE_OMNIBUS = "chef.use-omnibus"; private ChefProperties() { throw new AssertionError("intentionally unimplemented"); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/config/InstallChef.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.config; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Retention; import java.lang.annotation.Target; import jakarta.inject.Qualifier; /** * Used to configure the Chef install script. */ @Target({ METHOD, PARAMETER, FIELD }) @Retention(RUNTIME) @Qualifier public @interface InstallChef { } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/config/Validator.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.config; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Retention; import java.lang.annotation.Target; import jakarta.inject.Qualifier; /** * Used to configure the validator client information. *

* In a Chef server it must be only one validator client. This client is used by * new nodes to autoregister themselves in the Chef server. */ @Target({ METHOD, PARAMETER, FIELD }) @Retention(RUNTIME) @Qualifier public @interface Validator { } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/domain/Attribute.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.domain; import static org.jclouds.chef.util.CollectionUtils.copyOfOrEmpty; import static com.google.common.base.Preconditions.checkNotNull; import java.beans.ConstructorProperties; import java.util.List; import java.util.Set; import org.jclouds.domain.JsonBall; import org.jclouds.javax.annotation.Nullable; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.gson.annotations.SerializedName; /** * An attribute in a cookbook metadata. */ public class Attribute { public static Builder builder() { return new Builder(); } public static class Builder { private String required; private boolean calculated; private ImmutableSet.Builder choice = ImmutableSet.builder(); private JsonBall defaultValue; private String type; private ImmutableList.Builder recipes = ImmutableList.builder(); private String displayName; private String description; public Builder required(String required) { this.required = checkNotNull(required, "required"); return this; } public Builder calculated(boolean calculated) { this.calculated = calculated; return this; } public Builder choice(String choice) { this.choice.add(checkNotNull(choice, "choice")); return this; } public Builder choices(Iterable choices) { this.choice.addAll(checkNotNull(choices, "choices")); return this; } public Builder defaultValue(JsonBall defaultValue) { this.defaultValue = checkNotNull(defaultValue, "defaultValue"); return this; } public Builder type(String type) { this.type = checkNotNull(type, "type"); return this; } public Builder recipe(String recipe) { this.recipes.add(checkNotNull(recipe, "recipe")); return this; } public Builder recipes(Iterable recipes) { this.recipes.addAll(checkNotNull(recipes, "recipes")); return this; } public Builder displayName(String displayName) { this.displayName = checkNotNull(displayName, "displayName"); return this; } public Builder description(String description) { this.description = checkNotNull(description, "description"); return this; } public Attribute build() { return new Attribute(required, calculated, choice.build(), defaultValue, type, recipes.build(), displayName, description); } } private final String required; private final boolean calculated; private final Set choice; @SerializedName("default") private final JsonBall defaultValue; private final String type; private final List recipes; @SerializedName("display_name") private final String displayName; private final String description; @ConstructorProperties({ "required", "calculated", "choice", "default", "type", "recipes", "display_name", "description" }) protected Attribute(String required, boolean calculated, @Nullable Set choice, JsonBall defaultValue, String type, @Nullable List recipes, String displayName, String description) { this.required = required; this.calculated = calculated; this.choice = copyOfOrEmpty(choice); this.defaultValue = defaultValue; this.type = type; this.recipes = copyOfOrEmpty(recipes); this.displayName = displayName; this.description = description; } public String getRequired() { return required; } public boolean isCalculated() { return calculated; } public Set getChoice() { return choice; } public JsonBall getDefaultValue() { return defaultValue; } public String getType() { return type; } public List getRecipes() { return recipes; } public String getDisplayName() { return displayName; } public String getDescription() { return description; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + (calculated ? 1231 : 1237); result = prime * result + ((choice == null) ? 0 : choice.hashCode()); result = prime * result + ((defaultValue == null) ? 0 : defaultValue.hashCode()); result = prime * result + ((description == null) ? 0 : description.hashCode()); result = prime * result + ((displayName == null) ? 0 : displayName.hashCode()); result = prime * result + ((recipes == null) ? 0 : recipes.hashCode()); result = prime * result + ((required == null) ? 0 : required.hashCode()); result = prime * result + ((type == null) ? 0 : type.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Attribute other = (Attribute) obj; if (calculated != other.calculated) return false; if (choice == null) { if (other.choice != null) return false; } else if (!choice.equals(other.choice)) return false; if (defaultValue == null) { if (other.defaultValue != null) return false; } else if (!defaultValue.equals(other.defaultValue)) return false; if (description == null) { if (other.description != null) return false; } else if (!description.equals(other.description)) return false; if (displayName == null) { if (other.displayName != null) return false; } else if (!displayName.equals(other.displayName)) return false; if (recipes == null) { if (other.recipes != null) return false; } else if (!recipes.equals(other.recipes)) return false; if (required == null) { if (other.required != null) return false; } else if (!required.equals(other.required)) return false; if (type == null) { if (other.type != null) return false; } else if (!type.equals(other.type)) return false; return true; } @Override public String toString() { return "Attribute [calculated=" + calculated + ", choice=" + choice + ", defaultValue=" + defaultValue + ", description=" + description + ", displayName=" + displayName + ", recipes=" + recipes + ", required=" + required + ", type=" + type + "]"; } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/domain/BootstrapConfig.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.domain; import static com.google.common.base.Preconditions.checkNotNull; import java.beans.ConstructorProperties; import java.util.List; import org.jclouds.domain.JsonBall; import org.jclouds.javax.annotation.Nullable; import com.google.common.collect.ImmutableList; import com.google.gson.annotations.SerializedName; /** * Configures how the nodes in a group will bootstrap. * * @since 1.7 */ public class BootstrapConfig { public static enum SSLVerifyMode { NONE, PEER; @Override public String toString() { return ":verify_" + name().toLowerCase(); } public static SSLVerifyMode fromValue(String value) { return valueOf(value.replaceAll(":verify_", "").toUpperCase()); } } public static Builder builder() { return new Builder(); } public static class Builder { private ImmutableList.Builder runList = ImmutableList.builder(); private String environment; private JsonBall attribtues; private String sslCAFile; private String sslCAPath; private SSLVerifyMode sslVerifyMode; private Boolean verifyApiCert; /** * Sets the run list that will be executed in the nodes of the group. */ public Builder runList(Iterable runList) { this.runList.addAll(checkNotNull(runList, "runList")); return this; } /** * Sets the environment where the nodes in the group will be deployed. */ public Builder environment(String environment) { this.environment = checkNotNull(environment, "environment"); return this; } /** * Sets the attributes that will be populated to the deployed nodes. */ public Builder attributes(JsonBall attributes) { this.attribtues = checkNotNull(attributes, "attributes"); return this; } /** * The file in which the OpenSSL key is saved. To be used by the Chef * client to verify the certificate of the Chef Server. */ public Builder sslCAFile(String sslCAFile) { this.sslCAFile = checkNotNull(sslCAFile, "sslCAFile"); return this; } /** * The path to where the OpenSSL keys that are used by the Chef client are * located. */ public Builder sslCAPath(String sslCAPath) { this.sslCAPath = checkNotNull(sslCAPath, "sslCAPath"); return this; } /** * The verify mode for HTTPS requests. *

    *
  • NONE - to do no validation of SSL certificates.
  • *
  • PEER - to do validation of all SSL certificate, including the Chef * server connections
  • *
*/ public Builder sslVerifyMode(SSLVerifyMode sslVerifyMode) { this.sslVerifyMode = checkNotNull(sslVerifyMode, "sslVerifyMode"); return this; } /** * Use to only do SSL validation of the Chef server connection; may be * needed if the Chef client needs to talk to other services that have * broken SSL certificates. */ public Builder verifyApiCert(boolean verifyApiCert) { this.verifyApiCert = verifyApiCert; return this; } public BootstrapConfig build() { return new BootstrapConfig(runList.build(), environment, attribtues, sslCAFile, sslCAPath, sslVerifyMode, verifyApiCert); } } @SerializedName("run_list") private final List runList; @Nullable private final String environment; @Nullable private final JsonBall attributes; @SerializedName("ssl_ca_file") @Nullable private final String sslCAFile; @SerializedName("ssl_ca_path") @Nullable private final String sslCAPath; @SerializedName("ssl_verify_mode") @Nullable private final SSLVerifyMode sslVerifyMode; @SerializedName("verify_api_cert") @Nullable private final Boolean verifyApiCert; @ConstructorProperties({ "run_list", "environment", "attributes", "ssl_ca_file", "ssl_ca_path", "ssl_verify_mode", "verify_api_cert" }) protected BootstrapConfig(List runList, @Nullable String environment, @Nullable JsonBall attributes, @Nullable String sslCAFile, @Nullable String sslCAPath, @Nullable SSLVerifyMode sslVerifyMode, @Nullable Boolean verifyApiCert) { this.runList = ImmutableList.copyOf(checkNotNull(runList, "runList")); this.environment = environment; this.attributes = attributes; this.sslCAFile = sslCAFile; this.sslCAPath = sslCAPath; this.sslVerifyMode = sslVerifyMode; this.verifyApiCert = verifyApiCert; } public List getRunList() { return runList; } @Nullable public String getEnvironment() { return environment; } @Nullable public JsonBall getAttributes() { return attributes; } @Nullable public String getSslCAFile() { return sslCAFile; } @Nullable public String getSslCAPath() { return sslCAPath; } @Nullable public SSLVerifyMode getSslVerifyMode() { return sslVerifyMode; } @Nullable public Boolean getVerifyApiCert() { return verifyApiCert; } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/domain/ChecksumStatus.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.domain; import static com.google.common.base.Preconditions.checkNotNull; import java.beans.ConstructorProperties; import java.net.URI; import com.google.gson.annotations.SerializedName; /** * The checksum of an uploaded resource. */ public class ChecksumStatus { public static Builder builder() { return new Builder(); } public static class Builder { private URI url; private boolean needsUpload; public Builder url(URI url) { this.url = checkNotNull(url, "url"); return this; } public Builder needsUpload(boolean needsUpload) { this.needsUpload = needsUpload; return this; } public ChecksumStatus build() { return new ChecksumStatus(url, needsUpload); } } private final URI url; @SerializedName("needs_upload") private final boolean needsUpload; @ConstructorProperties({ "url", "needs_upload" }) protected ChecksumStatus(URI url, boolean needsUpload) { this.url = url; this.needsUpload = needsUpload; } public URI getUrl() { return url; } public boolean needsUpload() { return needsUpload; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + (needsUpload ? 1231 : 1237); result = prime * result + ((url == null) ? 0 : url.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; ChecksumStatus other = (ChecksumStatus) obj; if (needsUpload != other.needsUpload) return false; if (url == null) { if (other.url != null) return false; } else if (!url.equals(other.url)) return false; return true; } @Override public String toString() { return "ChecksumStatus [needsUpload=" + needsUpload + ", url=" + url + "]"; } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/domain/Client.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.domain; import static com.google.common.base.Preconditions.checkNotNull; import java.beans.ConstructorProperties; import java.security.PrivateKey; import java.security.PublicKey; import java.security.cert.X509Certificate; import org.jclouds.javax.annotation.Nullable; import com.google.gson.annotations.SerializedName; /** * Client object. */ public class Client { public static Builder builder() { return new Builder(); } public static class Builder { private X509Certificate certificate; private PrivateKey privateKey; private String orgname; private String clientname; private String name; private boolean validator; private PublicKey publicKey; public Builder certificate(X509Certificate certificate) { this.certificate = checkNotNull(certificate, "certificate"); return this; } public Builder privateKey(PrivateKey privateKey) { this.privateKey = checkNotNull(privateKey, "privateKey"); return this; } public Builder publicKey(PublicKey publicKey) { this.publicKey = checkNotNull(publicKey, "publicKey"); return this; } public Builder orgname(String orgname) { this.orgname = checkNotNull(orgname, "orgname"); return this; } public Builder clientname(String clientname) { this.clientname = checkNotNull(clientname, "clientname"); return this; } public Builder name(String name) { this.name = checkNotNull(name, "name"); return this; } public Builder isValidator(boolean validator) { this.validator = validator; return this; } public Client build() { return new Client(certificate, orgname, clientname, name, validator, privateKey, publicKey); } } private final X509Certificate certificate; @SerializedName("private_key") private final PrivateKey privateKey; @SerializedName("public_key") private final PublicKey publicKey; private final String orgname; private final String clientname; private final String name; private final boolean validator; @ConstructorProperties({ "certificate", "orgname", "clientname", "name", "validator", "private_key", "public_key"}) protected Client(X509Certificate certificate, String orgname, String clientname, String name, boolean validator, @Nullable PrivateKey privateKey, @Nullable PublicKey publicKey) { this.certificate = certificate; this.orgname = orgname; this.clientname = clientname; this.name = name; this.validator = validator; this.privateKey = privateKey; this.publicKey = publicKey; } public PublicKey getPublicKey() { return publicKey; } public PrivateKey getPrivateKey() { return privateKey; } public X509Certificate getCertificate() { return certificate; } public String getOrgname() { return orgname; } public String getClientname() { return clientname; } public String getName() { return name; } public boolean isValidator() { return validator; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((certificate == null) ? 0 : certificate.hashCode()); result = prime * result + ((clientname == null) ? 0 : clientname.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + ((orgname == null) ? 0 : orgname.hashCode()); result = prime * result + ((privateKey == null) ? 0 : privateKey.hashCode()); result = prime * result + ((publicKey == null) ? 0 : publicKey.hashCode()); result = prime * result + (validator ? 1231 : 1237); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Client other = (Client) obj; if (certificate == null) { if (other.certificate != null) return false; } else if (!certificate.equals(other.certificate)) return false; if (clientname == null) { if (other.clientname != null) return false; } else if (!clientname.equals(other.clientname)) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; if (orgname == null) { if (other.orgname != null) return false; } else if (!orgname.equals(other.orgname)) return false; if (publicKey == null) { if (other.publicKey != null) return false; } else if (!publicKey.equals(other.publicKey)) return false; if (privateKey == null) { if (other.privateKey != null) return false; } else if (!privateKey.equals(other.privateKey)) return false; if (validator != other.validator) return false; return true; } @Override public String toString() { return "Client [name=" + name + ", clientname=" + clientname + ", orgname=" + orgname + ", isValidator=" + validator + ", certificate=" + certificate + ", publicKey=" + publicKey + ", privateKey=" + (privateKey == null ? "not " : "") + "present]"; } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/domain/CookbookDefinition.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.domain; import static com.google.common.base.Preconditions.checkNotNull; import static org.jclouds.chef.util.CollectionUtils.copyOfOrEmpty; import java.beans.ConstructorProperties; import java.net.URI; import java.util.Set; import org.jclouds.javax.annotation.Nullable; import com.google.common.collect.ImmutableSet; /** * Cookbook definition as returned by the Chef server >= 0.10.8. */ public class CookbookDefinition { public static Builder builder() { return new Builder(); } public static class Builder { private String name; private URI url; private ImmutableSet.Builder versions = ImmutableSet.builder(); public Builder name(String name) { this.name = checkNotNull(name, "name"); return this; } public Builder url(URI url) { this.url = checkNotNull(url, "url"); return this; } public Builder version(Version version) { this.versions.add(checkNotNull(version, "version")); return this; } public Builder versions(Iterable versions) { this.versions.addAll(checkNotNull(versions, "versions")); return this; } public Builder from(CookbookDefinition def) { this.url = checkNotNull(def.getUrl(), "url"); this.versions.addAll(checkNotNull(def.getVersions(), "versions")); this.name = def.getName(); return this; } public CookbookDefinition build() { return new CookbookDefinition(name, url, versions.build()); } } private final String name; private final URI url; private final Set versions; @ConstructorProperties({"name", "url", "versions" }) protected CookbookDefinition(String name, URI url, @Nullable Set versions) { this.name = name; this.url = url; this.versions = copyOfOrEmpty(versions); } public String getName() { return name; } public URI getUrl() { return url; } public Set getVersions() { return versions; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + ((url == null) ? 0 : url.hashCode()); result = prime * result + ((versions == null) ? 0 : versions.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; CookbookDefinition other = (CookbookDefinition) obj; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; if (url == null) { if (other.url != null) return false; } else if (!url.equals(other.url)) return false; if (versions == null) { if (other.versions != null) return false; } else if (!versions.equals(other.versions)) return false; return true; } @Override public String toString() { return "CookbookDefinition [name=" + name + ", url=" + url + ", versions=" + versions + "]"; } public static class Version { public static Builder builder() { return new Builder(); } public static class Builder { private URI url; private String version; public Builder url(URI url) { this.url = checkNotNull(url, "url"); return this; } public Builder version(String version) { this.version = checkNotNull(version, "version"); return this; } public Version build() { return new Version(url, version); } } private final URI url; private final String version; @ConstructorProperties({ "url", "version" }) protected Version(URI url, String version) { this.url = url; this.version = version; } public URI getUrl() { return url; } public String getVersion() { return version; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((url == null) ? 0 : url.hashCode()); result = prime * result + ((version == null) ? 0 : version.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Version other = (Version) obj; if (url == null) { if (other.url != null) return false; } else if (!url.equals(other.url)) return false; if (version == null) { if (other.version != null) return false; } else if (!version.equals(other.version)) return false; return true; } @Override public String toString() { return "Version [url=" + url + ", version=" + version + "]"; } } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/domain/CookbookVersion.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.domain; import static com.google.common.base.Preconditions.checkNotNull; import static org.jclouds.chef.util.CollectionUtils.copyOfOrEmpty; import java.beans.ConstructorProperties; import java.util.Set; import org.jclouds.javax.annotation.Nullable; import com.google.common.collect.ImmutableSet; import com.google.gson.annotations.SerializedName; /** * Cookbook object. */ public class CookbookVersion { public static Builder builder(String name, String version) { return new Builder(name, version); } public static class Builder { private String cookbookName; private ImmutableSet.Builder definitions = ImmutableSet.builder(); private ImmutableSet.Builder attributes = ImmutableSet.builder(); private ImmutableSet.Builder files = ImmutableSet.builder(); private Metadata metadata = Metadata.builder().build(); private ImmutableSet.Builder providers = ImmutableSet.builder(); private ImmutableSet.Builder resources = ImmutableSet.builder(); private ImmutableSet.Builder templates = ImmutableSet.builder(); private ImmutableSet.Builder libraries = ImmutableSet.builder(); private String version; private ImmutableSet.Builder recipes = ImmutableSet.builder(); private ImmutableSet.Builder rootFiles = ImmutableSet.builder(); public Builder(String name, String version) { this.cookbookName = checkNotNull(name, "name"); this.version = checkNotNull(version, "version"); } public Builder cookbookName(String cookbookName) { this.cookbookName = checkNotNull(cookbookName, "cookbookName"); return this; } public Builder definition(Resource definition) { this.definitions.add(checkNotNull(definition, "definition")); return this; } public Builder definitions(Iterable definitions) { this.definitions.addAll(checkNotNull(definitions, "definitions")); return this; } public Builder attribute(Resource attribute) { this.attributes.add(checkNotNull(attribute, "attribute")); return this; } public Builder attributes(Iterable attributes) { this.attributes.addAll(checkNotNull(attributes, "attributes")); return this; } public Builder file(Resource file) { this.files.add(checkNotNull(file, "file")); return this; } public Builder files(Iterable files) { this.files.addAll(checkNotNull(files, "files")); return this; } public Builder metadata(Metadata metadata) { this.metadata = checkNotNull(metadata, "metadata"); return this; } public Builder provider(Resource provider) { this.providers.add(checkNotNull(provider, "provider")); return this; } public Builder providers(Iterable providers) { this.providers.addAll(checkNotNull(providers, "providers")); return this; } public Builder resource(Resource resource) { this.resources.add(checkNotNull(resource, "resource")); return this; } public Builder resources(Iterable resources) { this.resources.addAll(checkNotNull(resources, "resources")); return this; } public Builder template(Resource template) { this.templates.add(checkNotNull(template, "template")); return this; } public Builder templates(Iterable templates) { this.templates.addAll(checkNotNull(templates, "templates")); return this; } public Builder library(Resource library) { this.libraries.add(checkNotNull(library, "library")); return this; } public Builder libraries(Iterable libraries) { this.libraries.addAll(checkNotNull(libraries, "libraries")); return this; } public Builder version(String version) { this.version = checkNotNull(version, "version"); return this; } public Builder recipe(Resource recipe) { this.recipes.add(checkNotNull(recipe, "recipe")); return this; } public Builder recipes(Iterable recipes) { this.recipes.addAll(checkNotNull(recipes, "recipes")); return this; } public Builder rootFile(Resource rootFile) { this.rootFiles.add(checkNotNull(rootFile, "rootFile")); return this; } public Builder rootFiles(Iterable rootFiles) { this.rootFiles.addAll(checkNotNull(rootFiles, "rootFiles")); return this; } public CookbookVersion build() { return new CookbookVersion(checkNotNull(cookbookName, "name") + "-" + checkNotNull(version, "version"), definitions.build(), attributes.build(), files.build(), metadata, providers.build(), cookbookName, resources.build(), templates.build(), libraries.build(), version, recipes.build(), rootFiles.build()); } } private final String name; private final Set definitions; private final Set attributes; private final Set files; private final Metadata metadata; private final Set providers; @SerializedName("cookbook_name") private final String cookbookName; private final Set resources; private final Set templates; private final Set libraries; private final String version; private final Set recipes; @SerializedName("root_files") private final Set rootFiles; // internal @SerializedName("json_class") private String _jsonClass = "Chef::CookbookVersion"; @SerializedName("chef_type") private String _chefType = "cookbook_version"; @ConstructorProperties({ "name", "definitions", "attributes", "files", "metadata", "providers", "cookbook_name", "resources", "templates", "libraries", "version", "recipes", "root_files" }) protected CookbookVersion(String name, @Nullable Set definitions, @Nullable Set attributes, @Nullable Set files, Metadata metadata, @Nullable Set providers, String cookbookName, @Nullable Set resources, @Nullable Set templates, @Nullable Set libraries, String version, @Nullable Set recipes, @Nullable Set rootFiles) { this.name = name; this.definitions = copyOfOrEmpty(definitions); this.attributes = copyOfOrEmpty(attributes); this.files = copyOfOrEmpty(files); this.metadata = metadata; this.providers = copyOfOrEmpty(providers); this.cookbookName = cookbookName; this.resources = copyOfOrEmpty(resources); this.templates = copyOfOrEmpty(templates); this.libraries = copyOfOrEmpty(libraries); this.version = version; this.recipes = copyOfOrEmpty(recipes); this.rootFiles = copyOfOrEmpty(rootFiles); } public String getName() { return name; } public Set getDefinitions() { return definitions; } public Set getAttributes() { return attributes; } public Set getFiles() { return files; } public Metadata getMetadata() { return metadata; } public Set getSuppliers() { return providers; } public String getCookbookName() { return cookbookName; } public Set getResources() { return resources; } public Set getTemplates() { return templates; } public Set getLibraries() { return libraries; } public String getVersion() { return version; } public Set getRecipes() { return recipes; } public Set getRootFiles() { return rootFiles; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((attributes == null) ? 0 : attributes.hashCode()); result = prime * result + ((cookbookName == null) ? 0 : cookbookName.hashCode()); result = prime * result + ((definitions == null) ? 0 : definitions.hashCode()); result = prime * result + ((files == null) ? 0 : files.hashCode()); result = prime * result + ((libraries == null) ? 0 : libraries.hashCode()); result = prime * result + ((metadata == null) ? 0 : metadata.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + ((providers == null) ? 0 : providers.hashCode()); result = prime * result + ((recipes == null) ? 0 : recipes.hashCode()); result = prime * result + ((resources == null) ? 0 : resources.hashCode()); result = prime * result + ((rootFiles == null) ? 0 : rootFiles.hashCode()); result = prime * result + ((templates == null) ? 0 : templates.hashCode()); result = prime * result + ((version == null) ? 0 : version.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; CookbookVersion other = (CookbookVersion) obj; if (attributes == null) { if (other.attributes != null) return false; } else if (!attributes.equals(other.attributes)) return false; if (cookbookName == null) { if (other.cookbookName != null) return false; } else if (!cookbookName.equals(other.cookbookName)) return false; if (definitions == null) { if (other.definitions != null) return false; } else if (!definitions.equals(other.definitions)) return false; if (files == null) { if (other.files != null) return false; } else if (!files.equals(other.files)) return false; if (libraries == null) { if (other.libraries != null) return false; } else if (!libraries.equals(other.libraries)) return false; if (metadata == null) { if (other.metadata != null) return false; } else if (!metadata.equals(other.metadata)) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; if (providers == null) { if (other.providers != null) return false; } else if (!providers.equals(other.providers)) return false; if (recipes == null) { if (other.recipes != null) return false; } else if (!recipes.equals(other.recipes)) return false; if (resources == null) { if (other.resources != null) return false; } else if (!resources.equals(other.resources)) return false; if (rootFiles == null) { if (other.rootFiles != null) return false; } else if (!rootFiles.equals(other.rootFiles)) return false; if (templates == null) { if (other.templates != null) return false; } else if (!templates.equals(other.templates)) return false; if (version == null) { if (other.version != null) return false; } else if (!version.equals(other.version)) return false; return true; } @Override public String toString() { return "Cookbook [attributes=" + attributes + ", cookbookName=" + cookbookName + ", definitions=" + definitions + ", files=" + files + ", libraries=" + libraries + ", metadata=" + metadata + ", name=" + name + ", providers=" + providers + ", recipes=" + recipes + ", resources=" + resources + ", rootFiles=" + rootFiles + ", templates=" + templates + ", version=" + version + "]"; } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/domain/DatabagItem.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.domain; import static com.google.common.base.Preconditions.checkNotNull; import org.jclouds.domain.JsonBall; /** * An item in a data bag. */ public class DatabagItem extends JsonBall { private final String id; public DatabagItem(String id, String value) { super(value); this.id = checkNotNull(id, "id"); } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + ((id == null) ? 0 : id.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (getClass() != obj.getClass()) return false; DatabagItem other = (DatabagItem) obj; if (id == null) { if (other.id != null) return false; } else if (!id.equals(other.id)) return false; return true; } public String getId() { return id; } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/domain/Environment.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.domain; import static com.google.common.base.Preconditions.checkNotNull; import static org.jclouds.chef.util.CollectionUtils.copyOfOrEmpty; import java.beans.ConstructorProperties; import java.util.Map; import org.jclouds.domain.JsonBall; import org.jclouds.javax.annotation.Nullable; import com.google.common.collect.ImmutableMap; import com.google.gson.annotations.SerializedName; /** * An environment. */ public class Environment { public static Builder builder() { return new Builder(); } public static class Builder { private String name; private ImmutableMap.Builder attributes = ImmutableMap.builder(); private ImmutableMap.Builder overrideAttributes = ImmutableMap.builder(); private String description = ""; private ImmutableMap.Builder cookbookVersions = ImmutableMap.builder(); public Builder name(String name) { this.name = checkNotNull(name, "name"); return this; } public Builder attribute(String key, JsonBall value) { this.attributes.put(checkNotNull(key, "key"), checkNotNull(value, "value")); return this; } public Builder attributes(Map attributes) { this.attributes.putAll(checkNotNull(attributes, "attributes")); return this; } public Builder overrideAttribute(String key, JsonBall value) { this.overrideAttributes.put(checkNotNull(key, "key"), checkNotNull(value, "value")); return this; } public Builder overrideAttributes(Map overrideAttributes) { this.overrideAttributes.putAll(checkNotNull(overrideAttributes, "overrideAttributes")); return this; } public Builder cookbookVersion(String key, String version) { this.cookbookVersions.put(checkNotNull(key, "key"), checkNotNull(version, "version")); return this; } public Builder cookbookVersions(Map cookbookVersions) { this.cookbookVersions.putAll(checkNotNull(cookbookVersions, "cookbookVersions")); return this; } public Builder description(String description) { this.description = checkNotNull(description, "description"); return this; } public Environment build() { return new Environment(name, attributes.build(), overrideAttributes.build(), description, cookbookVersions.build()); } } private final String name; @SerializedName("default_attributes") private final Map attributes; @SerializedName("override_attributes") private final Map overrideAttributes; private final String description; @SerializedName("cookbook_versions") private final Map cookbookVersions; // internal @SerializedName("json_class") private final String _jsonClass = "Chef::Environment"; @SerializedName("chef_type") private final String _chefType = "environment"; @ConstructorProperties({ "name", "default_attributes", "override_attributes", "description", "cookbook_versions" }) protected Environment(String name, @Nullable Map attributes, @Nullable Map overrideAttributes, String description, @Nullable Map cookbookVersions) { this.name = name; this.attributes = copyOfOrEmpty(attributes); this.overrideAttributes = copyOfOrEmpty(overrideAttributes); this.description = description; this.cookbookVersions = copyOfOrEmpty(cookbookVersions); } public String getName() { return name; } public Map getAttributes() { return attributes; } public Map getOverrideAttributes() { return overrideAttributes; } public String getDescription() { return description; } public Map getCookbookVersions() { return cookbookVersions; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Environment that = (Environment) o; if (attributes != null ? !attributes.equals(that.attributes) : that.attributes != null) return false; if (cookbookVersions != null ? !cookbookVersions.equals(that.cookbookVersions) : that.cookbookVersions != null) return false; if (description != null ? !description.equals(that.description) : that.description != null) return false; if (!name.equals(that.name)) return false; if (overrideAttributes != null ? !overrideAttributes.equals(that.overrideAttributes) : that.overrideAttributes != null) return false; return true; } @Override public int hashCode() { int result = name.hashCode(); result = 31 * result + (attributes != null ? attributes.hashCode() : 0); result = 31 * result + (overrideAttributes != null ? overrideAttributes.hashCode() : 0); result = 31 * result + (description != null ? description.hashCode() : 0); result = 31 * result + (cookbookVersions != null ? cookbookVersions.hashCode() : 0); return result; } @Override public String toString() { return "Environment [" + "name='" + name + '\'' + ", attributes=" + attributes + ", overrideAttributes=" + overrideAttributes + ", description='" + description + '\'' + ", cookbookVersions=" + cookbookVersions + ']'; } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/domain/Group.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.domain; import static org.jclouds.chef.util.CollectionUtils.copyOfOrEmpty; import static com.google.common.base.Preconditions.checkNotNull; import java.beans.ConstructorProperties; import java.util.Set; import org.jclouds.javax.annotation.Nullable; import com.google.common.collect.ImmutableSet; /** * Group object. */ public class Group { public static Builder builder(String groupname) { return new Builder(groupname); } public static class Builder { private String name; private String groupname; private String orgname; private ImmutableSet.Builder actors = ImmutableSet.builder(); private ImmutableSet.Builder clients = ImmutableSet.builder(); private ImmutableSet.Builder groups = ImmutableSet.builder(); private ImmutableSet.Builder users = ImmutableSet.builder(); public Builder(String groupname) { this.groupname = groupname; } public Builder name(String name) { this.name = checkNotNull(name, "name"); return this; } public Builder groupname(String groupname) { this.groupname = checkNotNull(groupname, "groupname"); return this; } public Builder orgname(String orgname) { this.orgname = checkNotNull(orgname, "orgname"); return this; } public Builder actor(String actor) { this.actors.add(checkNotNull(actor, "actor")); return this; } public Builder actors(Iterable actors) { this.actors.addAll(checkNotNull(actors, "actors")); return this; } public Builder client(String client) { this.clients.add(checkNotNull(client, "client")); return this; } public Builder clients(Iterable clients) { this.clients.addAll(checkNotNull(clients, "clients")); return this; } public Builder group(String group) { this.groups.add(checkNotNull(group, "group")); return this; } public Builder groups(Iterable groups) { this.groups.addAll(checkNotNull(groups, "groups")); return this; } public Builder user(String user) { this.users.add(checkNotNull(user, "user")); return this; } public Builder users(Iterable users) { this.users.addAll(checkNotNull(users, "users")); return this; } public Group build() { return new Group(name, checkNotNull(groupname, "groupname"), orgname, actors.build(), clients.build(), groups.build(), users.build()); } } private final String name; private final String groupname; private final String orgname; private final Set actors; private final Set clients; private final Set groups; private final Set users; @ConstructorProperties({ "name", "groupname", "orgname", "actors", "clients", "groups", "users" }) public Group(String name, String groupname, String orgname, @Nullable Set actors, @Nullable Set clients, @Nullable Set groups, @Nullable Set users) { this.name = name; this.groupname = groupname; this.orgname = orgname; this.actors = copyOfOrEmpty(actors); this.clients = copyOfOrEmpty(clients); this.groups = copyOfOrEmpty(groups); this.users = copyOfOrEmpty(users); } public String getName() { return name; } public String getGroupname() { return groupname; } public String getOrgname() { return orgname; } public Set getActors() { return actors; } public Set getClients() { return clients; } public Set getGroups() { return groups; } public Set getUsers() { return users; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + (groupname == null ? 0 : groupname.hashCode()); result = prime * result + (name == null ? 0 : name.hashCode()); result = prime * result + (orgname == null ? 0 : orgname.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } Group other = (Group) obj; if (groupname == null) { if (other.groupname != null) { return false; } } else if (!groupname.equals(other.groupname)) { return false; } if (name == null) { if (other.name != null) { return false; } } else if (!name.equals(other.name)) { return false; } if (orgname == null) { if (other.orgname != null) { return false; } } else if (!orgname.equals(other.orgname)) { return false; } return true; } @Override public String toString() { return "Group [name=" + name + ", groupname=" + groupname + ", orgname=" + orgname + ", actors=" + actors + ", clients=" + clients + ", groups=" + groups + ", users=" + users + "]"; } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/domain/Grouping.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.domain; import static com.google.common.base.Preconditions.checkNotNull; import java.beans.ConstructorProperties; /** * Information of a group of attributes in a namespace. */ public class Grouping { public static Builder builder() { return new Builder(); } public static class Builder { private String title; private String description; public Builder title(String title) { this.title = checkNotNull(title, "title"); return this; } public Builder description(String description) { this.description = description; return this; } public Grouping build() { return new Grouping(title, description); } } private final String title; private final String description; @ConstructorProperties({ "title", "description" }) protected Grouping(String title, String description) { this.title = title; this.description = description; } public String getTitle() { return title; } public String getDescription() { return description; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((description == null) ? 0 : description.hashCode()); result = prime * result + ((title == null) ? 0 : title.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Grouping other = (Grouping) obj; if (description == null) { if (other.description != null) return false; } else if (!description.equals(other.description)) return false; if (title == null) { if (other.title != null) return false; } else if (!title.equals(other.title)) return false; return true; } @Override public String toString() { return "Grouping [title=" + title + ", description=" + description + "]"; } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/domain/Metadata.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.domain; import static com.google.common.base.Preconditions.checkNotNull; import static org.jclouds.chef.util.CollectionUtils.copyOfOrEmpty; import java.beans.ConstructorProperties; import java.util.Map; import org.jclouds.javax.annotation.Nullable; import com.google.common.collect.ImmutableMap; import com.google.gson.annotations.SerializedName; /** * A metadata object. */ public class Metadata { public static Builder builder() { return new Builder(); } public static class Builder { private String license; private String maintainer; private ImmutableMap.Builder suggestions = ImmutableMap.builder(); private ImmutableMap.Builder dependencies = ImmutableMap.builder(); private String maintainerEmail; private ImmutableMap.Builder conflicting = ImmutableMap.builder(); private String description; private ImmutableMap.Builder providing = ImmutableMap.builder(); private ImmutableMap.Builder platforms = ImmutableMap.builder(); private String version; private ImmutableMap.Builder recipes = ImmutableMap.builder(); private ImmutableMap.Builder replacing = ImmutableMap.builder(); private String name; private ImmutableMap.Builder groupings = ImmutableMap.builder(); private String longDescription; private ImmutableMap.Builder attributes = ImmutableMap.builder(); private ImmutableMap.Builder recommendations = ImmutableMap.builder(); public Builder license(String license) { this.license = checkNotNull(license, "license"); return this; } public Builder maintainer(String maintainer) { this.maintainer = checkNotNull(maintainer, "maintainer"); return this; } public Builder suggestion(String key, String value) { this.suggestions.put(checkNotNull(key, "key"), checkNotNull(value, "value")); return this; } public Builder suggestions(Map suggestions) { this.suggestions.putAll(checkNotNull(suggestions, "suggestions")); return this; } public Builder dependency(String key, String value) { this.dependencies.put(checkNotNull(key, "key"), checkNotNull(value, "value")); return this; } public Builder dependencies(Map dependencies) { this.dependencies.putAll(checkNotNull(dependencies, "dependencies")); return this; } public Builder maintainerEmail(String maintainerEmail) { this.maintainerEmail = checkNotNull(maintainerEmail, "maintainerEmail"); return this; } public Builder conflicting(String key, String value) { this.conflicting.put(checkNotNull(key, "key"), checkNotNull(value, "value")); return this; } public Builder conflicting(Map conflicting) { this.conflicting.putAll(checkNotNull(conflicting, "conflicting")); return this; } public Builder description(String description) { this.description = checkNotNull(description, "description"); return this; } public Builder providing(String key, String value) { this.providing.put(checkNotNull(key, "key"), checkNotNull(value, "value")); return this; } public Builder providing(Map providing) { this.providing.putAll(checkNotNull(providing, "providing")); return this; } public Builder platform(String key, String value) { this.platforms.put(checkNotNull(key, "key"), checkNotNull(value, "value")); return this; } public Builder platforms(Map platforms) { this.platforms.putAll(checkNotNull(platforms, "platforms")); return this; } public Builder version(String version) { this.version = checkNotNull(version, "version"); return this; } public Builder recipe(String key, String value) { this.recipes.put(checkNotNull(key, "key"), checkNotNull(value, "value")); return this; } public Builder recipes(Map recipes) { this.recipes.putAll(checkNotNull(recipes, "recipes")); return this; } public Builder replacing(String key, String value) { this.replacing.put(checkNotNull(key, "key"), checkNotNull(value, "value")); return this; } public Builder replacing(Map replacing) { this.replacing.putAll(checkNotNull(replacing, "replacing")); return this; } public Builder name(String name) { this.name = checkNotNull(name, "name"); return this; } public Builder grouping(String key, Grouping value) { this.groupings.put(checkNotNull(key, "key"), checkNotNull(value, "value")); return this; } public Builder grouping(Map groupings) { this.groupings.putAll(checkNotNull(groupings, "groupings")); return this; } public Builder longDescription(String longDescription) { this.longDescription = checkNotNull(longDescription, "longDescription"); return this; } public Builder attribute(String key, Attribute value) { this.attributes.put(checkNotNull(key, "key"), checkNotNull(value, "value")); return this; } public Builder attributes(Map attributes) { this.attributes.putAll(checkNotNull(attributes, "attributes")); return this; } public Builder recommendation(String key, String value) { this.recommendations.put(checkNotNull(key, "key"), checkNotNull(value, "value")); return this; } public Builder recommendations(Map recommendations) { this.recommendations.putAll(checkNotNull(recommendations, "recommendations")); return this; } public Metadata build() { return new Metadata(license, maintainer, suggestions.build(), dependencies.build(), maintainerEmail, conflicting.build(), description, providing.build(), platforms.build(), version, recipes.build(), replacing.build(), name, groupings.build(), longDescription, attributes.build(), recommendations.build()); } } private final String license; private final String maintainer; private final Map suggestions; private final Map dependencies; @SerializedName("maintainer_email") private final String maintainerEmail; private final Map conflicting; private final String description; private final Map providing; private final Map platforms; private final String version; private final Map recipes; private final Map replacing; private final String name; private final Map groupings; @SerializedName("long_description") private final String longDescription; private final Map attributes; private final Map recommendations; @ConstructorProperties({ "license", "maintainer", "suggestions", "dependencies", "maintainer_email", "conflicting", "description", "providing", "platforms", "version", "recipes", "replacing", "name", "groupings", "long_description", "attributes", "recommendations" }) protected Metadata(String license, String maintainer, @Nullable Map suggestions, @Nullable Map dependencies, String maintainerEmail, @Nullable Map conflicting, String description, @Nullable Map providing, @Nullable Map platforms, String version, @Nullable Map recipes, @Nullable Map replacing, String name, @Nullable Map groupings, String longDescription, @Nullable Map attributes, @Nullable Map recommendations) { this.license = license; this.maintainer = maintainer; this.suggestions = copyOfOrEmpty(suggestions); this.dependencies = copyOfOrEmpty(dependencies); this.maintainerEmail = maintainerEmail; this.conflicting = copyOfOrEmpty(conflicting); this.description = description; this.providing = copyOfOrEmpty(providing); this.platforms = copyOfOrEmpty(platforms); this.version = version; this.recipes = copyOfOrEmpty(recipes); this.replacing = copyOfOrEmpty(replacing); this.name = name; this.groupings = copyOfOrEmpty(groupings); this.longDescription = longDescription; this.attributes = copyOfOrEmpty(attributes); this.recommendations = copyOfOrEmpty(recommendations); } public String getLicense() { return license; } public String getMaintainer() { return maintainer; } public Map getSuggestions() { return suggestions; } public Map getDependencies() { return dependencies; } public String getMaintainerEmail() { return maintainerEmail; } public Map getConflicting() { return conflicting; } public String getDescription() { return description; } public Map getProviding() { return providing; } public Map getPlatforms() { return platforms; } public String getVersion() { return version; } public Map getRecipes() { return recipes; } public Map getReplacing() { return replacing; } public String getName() { return name; } public Map getGroupings() { return groupings; } public String getLongDescription() { return longDescription; } public Map getAttributes() { return attributes; } public Map getRecommendations() { return recommendations; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((attributes == null) ? 0 : attributes.hashCode()); result = prime * result + ((conflicting == null) ? 0 : conflicting.hashCode()); result = prime * result + ((dependencies == null) ? 0 : dependencies.hashCode()); result = prime * result + ((description == null) ? 0 : description.hashCode()); result = prime * result + ((groupings == null) ? 0 : groupings.hashCode()); result = prime * result + ((license == null) ? 0 : license.hashCode()); result = prime * result + ((longDescription == null) ? 0 : longDescription.hashCode()); result = prime * result + ((maintainer == null) ? 0 : maintainer.hashCode()); result = prime * result + ((maintainerEmail == null) ? 0 : maintainerEmail.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + ((platforms == null) ? 0 : platforms.hashCode()); result = prime * result + ((providing == null) ? 0 : providing.hashCode()); result = prime * result + ((recipes == null) ? 0 : recipes.hashCode()); result = prime * result + ((recommendations == null) ? 0 : recommendations.hashCode()); result = prime * result + ((replacing == null) ? 0 : replacing.hashCode()); result = prime * result + ((suggestions == null) ? 0 : suggestions.hashCode()); result = prime * result + ((version == null) ? 0 : version.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Metadata other = (Metadata) obj; if (attributes == null) { if (other.attributes != null) return false; } else if (!attributes.equals(other.attributes)) return false; if (conflicting == null) { if (other.conflicting != null) return false; } else if (!conflicting.equals(other.conflicting)) return false; if (dependencies == null) { if (other.dependencies != null) return false; } else if (!dependencies.equals(other.dependencies)) return false; if (description == null) { if (other.description != null) return false; } else if (!description.equals(other.description)) return false; if (groupings == null) { if (other.groupings != null) return false; } else if (!groupings.equals(other.groupings)) return false; if (license == null) { if (other.license != null) return false; } else if (!license.equals(other.license)) return false; if (longDescription == null) { if (other.longDescription != null) return false; } else if (!longDescription.equals(other.longDescription)) return false; if (maintainer == null) { if (other.maintainer != null) return false; } else if (!maintainer.equals(other.maintainer)) return false; if (maintainerEmail == null) { if (other.maintainerEmail != null) return false; } else if (!maintainerEmail.equals(other.maintainerEmail)) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; if (platforms == null) { if (other.platforms != null) return false; } else if (!platforms.equals(other.platforms)) return false; if (providing == null) { if (other.providing != null) return false; } else if (!providing.equals(other.providing)) return false; if (recipes == null) { if (other.recipes != null) return false; } else if (!recipes.equals(other.recipes)) return false; if (recommendations == null) { if (other.recommendations != null) return false; } else if (!recommendations.equals(other.recommendations)) return false; if (replacing == null) { if (other.replacing != null) return false; } else if (!replacing.equals(other.replacing)) return false; if (suggestions == null) { if (other.suggestions != null) return false; } else if (!suggestions.equals(other.suggestions)) return false; if (version == null) { if (other.version != null) return false; } else if (!version.equals(other.version)) return false; return true; } @Override public String toString() { return "Metadata [attributes=" + attributes + ", conflicting=" + conflicting + ", dependencies=" + dependencies + ", description=" + description + ", groupings=" + groupings + ", license=" + license + ", longDescription=" + longDescription + ", maintainer=" + maintainer + ", maintainerEmail=" + maintainerEmail + ", name=" + name + ", platforms=" + platforms + ", providing=" + providing + ", recipes=" + recipes + ", recommendations=" + recommendations + ", replacing=" + replacing + ", suggestions=" + suggestions + ", version=" + version + "]"; } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/domain/Node.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.domain; import static com.google.common.base.Preconditions.checkNotNull; import static org.jclouds.chef.util.CollectionUtils.copyOfOrEmpty; import java.beans.ConstructorProperties; import java.util.List; import java.util.Map; import org.jclouds.domain.JsonBall; import org.jclouds.javax.annotation.Nullable; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.gson.annotations.SerializedName; /** * Node object. */ public class Node { public static Builder builder() { return new Builder(); } public static class Builder { private String name; private ImmutableMap.Builder normalAttributes = ImmutableMap.builder(); private ImmutableMap.Builder overrideAttributes = ImmutableMap.builder(); private ImmutableMap.Builder defaultAttributes = ImmutableMap.builder(); private ImmutableMap.Builder automaticAttributes = ImmutableMap.builder(); private ImmutableList.Builder runList = ImmutableList.builder(); private String environment; public Builder name(String name) { this.name = checkNotNull(name, "name"); return this; } public Builder normalAttribute(String key, JsonBall value) { this.normalAttributes.put(checkNotNull(key, "key"), checkNotNull(value, "value")); return this; } public Builder normalAttributes(Map normalAttributes) { this.normalAttributes.putAll(checkNotNull(normalAttributes, "normalAttributes")); return this; } public Builder overrideAttribute(String key, JsonBall value) { this.overrideAttributes.put(checkNotNull(key, "key"), checkNotNull(value, "value")); return this; } public Builder overrideAttributes(Map overrideAttributes) { this.overrideAttributes.putAll(checkNotNull(overrideAttributes, "overrideAttributes")); return this; } public Builder defaultAttribute(String key, JsonBall value) { this.defaultAttributes.put(checkNotNull(key, "key"), checkNotNull(value, "value")); return this; } public Builder defaultAttributes(Map defaultAttributes) { this.defaultAttributes.putAll(checkNotNull(defaultAttributes, "defaultAttributes")); return this; } public Builder automaticAttribute(String key, JsonBall value) { this.automaticAttributes.put(checkNotNull(key, "key"), checkNotNull(value, "value")); return this; } public Builder automaticAttributes(Map automaticAttribute) { this.automaticAttributes.putAll(checkNotNull(automaticAttribute, "automaticAttribute")); return this; } public Builder runListElement(String element) { this.runList.add(checkNotNull(element, "element")); return this; } public Builder runList(Iterable runList) { this.runList.addAll(checkNotNull(runList, "runList")); return this; } /** * @since Chef 0.10 */ public Builder environment(String environment) { this.environment = checkNotNull(environment, "environment"); return this; } public Node build() { return new Node(name, normalAttributes.build(), overrideAttributes.build(), defaultAttributes.build(), automaticAttributes.build(), runList.build(), environment); } } private final String name; @SerializedName("normal") private final Map normalAttributes; @SerializedName("override") private final Map overrideAttributes; @SerializedName("default") private final Map defaultAttributes; @SerializedName("automatic") private final Map automaticAttributes; @SerializedName("run_list") private final List runList; @SerializedName("chef_environment") private final String environment; // internal @SerializedName("json_class") private final String _jsonClass = "Chef::Node"; @SerializedName("chef_type") private final String _chefType = "node"; @ConstructorProperties({ "name", "normal", "override", "default", "automatic", "run_list", "chef_environment" }) protected Node(String name, @Nullable Map normalAttributes, @Nullable Map overrideAttributes, @Nullable Map defaultAttributes, @Nullable Map automaticAttributes, List runList, @Nullable String environment) { this.name = name; this.environment = environment; this.normalAttributes = copyOfOrEmpty(normalAttributes); this.overrideAttributes = copyOfOrEmpty(overrideAttributes); this.defaultAttributes = copyOfOrEmpty(defaultAttributes); this.automaticAttributes = copyOfOrEmpty(automaticAttributes); this.runList = copyOfOrEmpty(runList); } public String getName() { return name; } public Map getNormalAttributes() { return normalAttributes; } public Map getOverrideAttributes() { return overrideAttributes; } public Map getDefaultAttributes() { return defaultAttributes; } public Map getAutomaticAttributes() { return automaticAttributes; } public List getRunList() { return runList; } /** * @since Chef 0.10 */ public String getEnvironment() { return environment; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((_chefType == null) ? 0 : _chefType.hashCode()); result = prime * result + ((_jsonClass == null) ? 0 : _jsonClass.hashCode()); result = prime * result + ((automaticAttributes == null) ? 0 : automaticAttributes.hashCode()); result = prime * result + ((defaultAttributes == null) ? 0 : defaultAttributes.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + ((normalAttributes == null) ? 0 : normalAttributes.hashCode()); result = prime * result + ((overrideAttributes == null) ? 0 : overrideAttributes.hashCode()); result = prime * result + ((runList == null) ? 0 : runList.hashCode()); result = prime * result + ((environment == null) ? 0 : environment.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Node other = (Node) obj; if (_chefType == null) { if (other._chefType != null) return false; } else if (!_chefType.equals(other._chefType)) return false; if (_jsonClass == null) { if (other._jsonClass != null) return false; } else if (!_jsonClass.equals(other._jsonClass)) return false; if (automaticAttributes == null) { if (other.automaticAttributes != null) return false; } else if (!automaticAttributes.equals(other.automaticAttributes)) return false; if (defaultAttributes == null) { if (other.defaultAttributes != null) return false; } else if (!defaultAttributes.equals(other.defaultAttributes)) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; if (normalAttributes == null) { if (other.normalAttributes != null) return false; } else if (!normalAttributes.equals(other.normalAttributes)) return false; if (overrideAttributes == null) { if (other.overrideAttributes != null) return false; } else if (!overrideAttributes.equals(other.overrideAttributes)) return false; if (runList == null) { if (other.runList != null) return false; } else if (!runList.equals(other.runList)) return false; if (environment == null) { if (other.environment != null) return false; } else if (!environment.equals(other.environment)) return false; return true; } @Override public String toString() { return "Node [name=" + name + ", runList=" + runList + ", normalAttributes=" + normalAttributes + ", defaultAttributes=" + defaultAttributes + ", overrideAttributes=" + overrideAttributes + ", chefEnvironment=" + environment + ", automaticAttributes=" + automaticAttributes + "]"; } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/domain/Resource.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.domain; import static com.google.common.base.Preconditions.checkNotNull; import java.beans.ConstructorProperties; import java.net.URI; import java.util.Arrays; import org.jclouds.io.payloads.FilePayload; import com.google.common.primitives.Bytes; /** * Resource object. */ public class Resource { public static Builder builder() { return new Builder(); } public static class Builder { private String name; private URI url; private byte[] checksum; private String path; private String specificity = "default"; public Builder name(String name) { this.name = checkNotNull(name, "name"); return this; } public Builder url(URI url) { this.url = checkNotNull(url, "url"); return this; } public Builder checksum(byte[] checksum) { this.checksum = checkNotNull(checksum, "checksum"); return this; } public Builder path(String path) { this.path = checkNotNull(path, "path"); return this; } public Builder specificity(String specificity) { this.specificity = checkNotNull(specificity, "specificity"); return this; } public Builder fromPayload(FilePayload payload) { checkNotNull(payload, "payload"); this.name(payload.getRawContent().getName()); this.checksum(payload.getContentMetadata().getContentMD5()); this.path(payload.getRawContent().getPath()); return this; } public Resource build() { return new Resource(name, url, checksum, path, specificity); } } private final String name; private final URI url; private final byte[] checksum; private final String path; private final String specificity; @ConstructorProperties({ "name", "url", "checksum", "path", "specificity" }) protected Resource(String name, URI url, byte[] checksum, String path, String specificity) { this.name = name; this.url = url; this.checksum = checksum; this.path = path; this.specificity = specificity; } public String getName() { return name; } public URI getUrl() { return url; } public byte[] getChecksum() { return checksum; } public String getPath() { return path; } public String getSpecificity() { return specificity; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + Arrays.hashCode(checksum); result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + ((path == null) ? 0 : path.hashCode()); result = prime * result + ((specificity == null) ? 0 : specificity.hashCode()); result = prime * result + ((url == null) ? 0 : url.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Resource other = (Resource) obj; if (!Arrays.equals(checksum, other.checksum)) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; if (path == null) { if (other.path != null) return false; } else if (!path.equals(other.path)) return false; if (specificity == null) { if (other.specificity != null) return false; } else if (!specificity.equals(other.specificity)) return false; if (url == null) { if (other.url != null) return false; } else if (!url.equals(other.url)) return false; return true; } @Override public String toString() { return "Resource [checksum=" + Bytes.asList(checksum) + ", name=" + name + ", path=" + path + ", specificity=" + specificity + ", url=" + url + "]"; } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/domain/Role.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.domain; import static com.google.common.base.Preconditions.checkNotNull; import static org.jclouds.chef.util.CollectionUtils.copyOfOrEmpty; import java.beans.ConstructorProperties; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.jclouds.domain.JsonBall; import org.jclouds.javax.annotation.Nullable; import com.google.common.base.Function; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; import com.google.gson.annotations.SerializedName; /** * Role object. */ public class Role { public static Builder builder() { return new Builder(); } public static class Builder { private String name; private String description; private ImmutableMap.Builder overrideAttributes = ImmutableMap.builder(); private ImmutableMap.Builder defaultAttributes = ImmutableMap.builder(); private ImmutableList.Builder runList = ImmutableList.builder(); // envRunList is a nested set of collections. The Immutable* classes in google collections don't appear to // support this nested immutability, so the builder will utilize native collections as the envRunList is // assembled. An immutable, nested map of collections will be assembled in the build() method. private Map> envRunList = new HashMap>(); public Builder name(String name) { this.name = checkNotNull(name, "name"); return this; } public Builder description(String description) { this.description = checkNotNull(description, "description"); return this; } public Builder overrideAttribute(String key, JsonBall value) { this.overrideAttributes.put(checkNotNull(key, "key"), checkNotNull(value, "value")); return this; } public Builder overrideAttributes(Map overrideAttributes) { this.overrideAttributes.putAll(checkNotNull(overrideAttributes, "overrideAttributes")); return this; } public Builder defaultAttribute(String key, JsonBall value) { this.defaultAttributes.put(checkNotNull(key, "key"), checkNotNull(value, "value")); return this; } public Builder defaultAttributes(Map defaultAttributes) { this.defaultAttributes.putAll(checkNotNull(defaultAttributes, "defaultAttributes")); return this; } public Builder runListElement(String element) { this.runList.add(checkNotNull(element, "element")); return this; } public Builder runList(Iterable runList) { this.runList.addAll(checkNotNull(runList, "runList")); return this; } public Builder envRunList(Map> envRunList) { this.envRunList.putAll(checkNotNull(envRunList, "envRunList")); return this; } public Builder envRunList(String name, List runList) { this.envRunList.put(checkNotNull(name, "name"), checkNotNull(runList, "runList")); return this; } public Builder envRunListElement(String name, String value) { checkNotNull(name, "name"); checkNotNull(value, "value"); List runList = this.envRunList.get(name); if (runList == null) { runList = new ArrayList(); this.envRunList.put(name, runList); } runList.add(value); return this; } public Role build() { // Assemble an immutable envRunList where each entry is an immutable list of entries. Map> immutableEnvRunList = Maps.transformValues(envRunList, new Function, List>() { @Override public List apply(List input) { return ImmutableList.copyOf(input); } }); return new Role(name, description, defaultAttributes.build(), runList.build(), overrideAttributes.build(), immutableEnvRunList); } } private final String name; private final String description; @SerializedName("override_attributes") private final Map overrideAttributes; @SerializedName("default_attributes") private final Map defaultAttributes; @SerializedName("run_list") private final List runList; @SerializedName("env_run_lists") private Map> envRunList; // internal @SerializedName("json_class") private final String _jsonClass = "Chef::Role"; @SerializedName("chef_type") private final String _chefType = "role"; @ConstructorProperties({ "name", "description", "default_attributes", "run_list", "override_attributes", "env_run_lists" }) protected Role(String name, String description, @Nullable Map defaultAttributes, @Nullable List runList, @Nullable Map overrideAttributes, @Nullable Map> envRunList) { this.name = name; this.description = description; this.defaultAttributes = copyOfOrEmpty(defaultAttributes); this.runList = copyOfOrEmpty(runList); this.overrideAttributes = copyOfOrEmpty(overrideAttributes); this.envRunList = envRunList; } public String getName() { return name; } public String getDescription() { return description; } public Map getOverrideAttributes() { return overrideAttributes; } public Map getDefaultAttributes() { return defaultAttributes; } public List getRunList() { return runList; } public Map> getEnvRunList() { return envRunList; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((_chefType == null) ? 0 : _chefType.hashCode()); result = prime * result + ((_jsonClass == null) ? 0 : _jsonClass.hashCode()); result = prime * result + ((defaultAttributes == null) ? 0 : defaultAttributes.hashCode()); result = prime * result + ((description == null) ? 0 : description.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + ((overrideAttributes == null) ? 0 : overrideAttributes.hashCode()); result = prime * result + ((runList == null) ? 0 : runList.hashCode()); result = prime * result + ((envRunList == null) ? 0 : envRunList.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Role other = (Role) obj; if (_chefType == null) { if (other._chefType != null) return false; } else if (!_chefType.equals(other._chefType)) return false; if (_jsonClass == null) { if (other._jsonClass != null) return false; } else if (!_jsonClass.equals(other._jsonClass)) return false; if (defaultAttributes == null) { if (other.defaultAttributes != null) return false; } else if (!defaultAttributes.equals(other.defaultAttributes)) return false; if (description == null) { if (other.description != null) return false; } else if (!description.equals(other.description)) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; if (overrideAttributes == null) { if (other.overrideAttributes != null) return false; } else if (!overrideAttributes.equals(other.overrideAttributes)) return false; if (runList == null) { if (other.runList != null) return false; } else if (!runList.equals(other.runList)) return false; if (envRunList == null) { if (other.envRunList != null) return false; } else if (!envRunList.equals(other.envRunList)) return false; return true; } @Override public String toString() { return "Role [name=" + name + ", description=" + description + ", defaultAttributes=" + defaultAttributes + ", overrideAttributes=" + overrideAttributes + ", runList=" + runList + ", envRunList=" + this.envRunList + "]"; } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/domain/Sandbox.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.domain; import static com.google.common.base.Preconditions.checkNotNull; import static org.jclouds.chef.util.CollectionUtils.copyOfOrEmpty; import java.beans.ConstructorProperties; import java.util.Date; import java.util.Set; import org.jclouds.javax.annotation.Nullable; import com.google.common.collect.ImmutableSet; import com.google.gson.annotations.SerializedName; /** * Sandbox object. */ public class Sandbox { public static Builder builder() { return new Builder(); } public static class Builder { private String rev; private boolean isCompleted; private Date createTime; private ImmutableSet.Builder checksums = ImmutableSet.builder(); private String name; private String guid; public Builder rev(String rev) { this.rev = checkNotNull(rev, "rev"); return this; } public Builder isCompleted(boolean isCompleted) { this.isCompleted = isCompleted; return this; } public Builder createTime(Date createTime) { this.createTime = createTime; return this; } public Builder checksum(String checksum) { this.checksums.add(checkNotNull(checksum, "checksum")); return this; } public Builder checksums(Iterable checksums) { this.checksums.addAll(checkNotNull(checksums, "checksums")); return this; } public Builder name(String name) { this.name = checkNotNull(name, "name"); return this; } public Builder guid(String guid) { this.guid = checkNotNull(guid, "guid"); return this; } public Sandbox build() { return new Sandbox(rev, isCompleted, createTime, checksums.build(), name, guid); } } @SerializedName("_rev") private final String rev; @SerializedName("is_completed") private final boolean isCompleted; @SerializedName("create_time") private final Date createTime; private final Set checksums; private final String name; private final String guid; // internal @SerializedName("json_class") private final String _jsonClass = "Chef::Sandbox"; @SerializedName("chef_type") private final String _chefType = "sandbox"; @ConstructorProperties({ "_rev", "is_completed", "create_time", "checksums", "name", "guid" }) protected Sandbox(String rev, boolean isCompleted, Date createTime, @Nullable Set checksums, String name, String guid) { this.rev = rev; this.isCompleted = isCompleted; this.createTime = createTime; this.checksums = copyOfOrEmpty(checksums); this.name = name; this.guid = guid; } public String getRev() { return rev; } public boolean isCompleted() { return isCompleted; } public Date getCreateTime() { return createTime; } public Set getChecksums() { return checksums; } public String getName() { return name; } public String getGuid() { return guid; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((checksums == null) ? 0 : checksums.hashCode()); result = prime * result + ((createTime == null) ? 0 : createTime.hashCode()); result = prime * result + ((guid == null) ? 0 : guid.hashCode()); result = prime * result + (isCompleted ? 1231 : 1237); result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + ((rev == null) ? 0 : rev.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Sandbox other = (Sandbox) obj; if (checksums == null) { if (other.checksums != null) return false; } else if (!checksums.equals(other.checksums)) return false; if (createTime == null) { if (other.createTime != null) return false; } else if (!createTime.equals(other.createTime)) return false; if (guid == null) { if (other.guid != null) return false; } else if (!guid.equals(other.guid)) return false; if (isCompleted != other.isCompleted) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; if (rev == null) { if (other.rev != null) return false; } else if (!rev.equals(other.rev)) return false; return true; } @Override public String toString() { return "Sandbox [checksums=" + checksums + ", createTime=" + createTime + ", guid=" + guid + ", isCompleted=" + isCompleted + ", name=" + name + ", rev=" + rev + "]"; } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/domain/SearchResult.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.domain; import java.util.LinkedHashSet; import com.google.common.collect.Iterables; /** * A result of a search. */ public class SearchResult extends LinkedHashSet { private static final long serialVersionUID = 4000610660948065287L; private long start; SearchResult() { } public SearchResult(long start, Iterable results) { this.start = start; Iterables.addAll(this, results); } /** * * @return the result position this started from from */ long getStart() { return start; } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/domain/UploadSandbox.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.domain; import static com.google.common.base.Preconditions.checkNotNull; import static org.jclouds.chef.util.CollectionUtils.copyOfOrEmpty; import java.beans.ConstructorProperties; import java.net.URI; import java.util.List; import java.util.Map; import org.jclouds.javax.annotation.Nullable; import com.google.common.collect.ImmutableMap; import com.google.gson.annotations.SerializedName; /** * An upload sandbox. */ public class UploadSandbox { public static Builder builder() { return new Builder(); } public static class Builder { private URI uri; private ImmutableMap.Builder, ChecksumStatus> checksums = ImmutableMap.builder(); private String sandboxId; public Builder uri(URI uri) { this.uri = checkNotNull(uri, "uri"); return this; } public Builder checksum(List key, ChecksumStatus value) { this.checksums.put(checkNotNull(key, "key"), checkNotNull(value, "value")); return this; } public Builder checksums(Map, ChecksumStatus> checksums) { this.checksums.putAll(checkNotNull(checksums, "checksums")); return this; } public Builder sandboxId(String sandboxId) { this.sandboxId = checkNotNull(sandboxId, "sandboxId"); return this; } public UploadSandbox build() { return new UploadSandbox(uri, checksums.build(), sandboxId); } } private final URI uri; private final Map, ChecksumStatus> checksums; @SerializedName("sandbox_id") private final String sandboxId; @ConstructorProperties({ "uri", "checksums", "sandbox_id" }) protected UploadSandbox(URI uri, @Nullable Map, ChecksumStatus> checksums, String sandboxId) { this.uri = uri; this.checksums = copyOfOrEmpty(checksums); this.sandboxId = sandboxId; } public URI getUri() { return uri; } public Map, ChecksumStatus> getChecksums() { return checksums; } public String getSandboxId() { return sandboxId; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((checksums == null) ? 0 : checksums.hashCode()); result = prime * result + ((sandboxId == null) ? 0 : sandboxId.hashCode()); result = prime * result + ((uri == null) ? 0 : uri.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; UploadSandbox other = (UploadSandbox) obj; if (checksums == null) { if (other.checksums != null) return false; } else if (!checksums.equals(other.checksums)) return false; if (sandboxId == null) { if (other.sandboxId != null) return false; } else if (!sandboxId.equals(other.sandboxId)) return false; if (uri == null) { if (other.uri != null) return false; } else if (!uri.equals(other.uri)) return false; return true; } @Override public String toString() { return "UploadSandbox [checksums=" + checksums + ", id=" + sandboxId + ", uri=" + uri + "]"; } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/domain/User.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.domain; import static com.google.common.base.Preconditions.checkNotNull; import java.beans.ConstructorProperties; import java.security.PublicKey; import com.google.gson.annotations.SerializedName; /** * User object. */ public class User { public static Builder builder() { return new Builder(); } public static class Builder { private String username; private String firstName; private String middleName; private String lastName; private String displayName; private String email; private PublicKey publicKey; public Builder username(String username) { this.username = checkNotNull(username, "username"); return this; } public Builder firstName(String firstName) { this.firstName = checkNotNull(firstName, "firstName"); return this; } public Builder middleName(String middleName) { this.middleName = checkNotNull(middleName, "middleName"); return this; } public Builder lastName(String lastName) { this.lastName = checkNotNull(lastName, "lastName"); return this; } public Builder displayName(String displayName) { this.displayName = checkNotNull(displayName, "displayName"); return this; } public Builder email(String email) { this.email = checkNotNull(email, "email"); return this; } public Builder publicKey(PublicKey publicKey) { this.publicKey = checkNotNull(publicKey, "publicKey"); return this; } public User build() { return new User(username, firstName, middleName, lastName, displayName, email, publicKey); } } private final String username; @SerializedName("first_name") private final String firstName; @SerializedName("middle_name") private final String middleName; @SerializedName("last_name") private final String lastName; @SerializedName("display_name") private final String displayName; private final String email; @SerializedName("public_key") private final PublicKey publicKey; @ConstructorProperties({ "username", "first_name", "middle_name", "last_name", "display_name", "email", "public_key" }) protected User(String username, String firstName, String middleName, String lastName, String displayName, String email, PublicKey publicKey) { this.username = username; this.firstName = firstName; this.middleName = middleName; this.lastName = lastName; this.displayName = displayName; this.email = email; this.publicKey = publicKey; } public String getUsername() { return username; } public String getFirstName() { return firstName; } public String getMiddleName() { return middleName; } public String getLastName() { return lastName; } public String getDisplayName() { return displayName; } public String getEmail() { return email; } public PublicKey getPublicKey() { return publicKey; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + (displayName == null ? 0 : displayName.hashCode()); result = prime * result + (email == null ? 0 : email.hashCode()); result = prime * result + (firstName == null ? 0 : firstName.hashCode()); result = prime * result + (lastName == null ? 0 : lastName.hashCode()); result = prime * result + (middleName == null ? 0 : middleName.hashCode()); result = prime * result + (publicKey == null ? 0 : publicKey.hashCode()); result = prime * result + (username == null ? 0 : username.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } User other = (User) obj; if (displayName == null) { if (other.displayName != null) { return false; } } else if (!displayName.equals(other.displayName)) { return false; } if (email == null) { if (other.email != null) { return false; } } else if (!email.equals(other.email)) { return false; } if (firstName == null) { if (other.firstName != null) { return false; } } else if (!firstName.equals(other.firstName)) { return false; } if (lastName == null) { if (other.lastName != null) { return false; } } else if (!lastName.equals(other.lastName)) { return false; } if (middleName == null) { if (other.middleName != null) { return false; } } else if (!middleName.equals(other.middleName)) { return false; } if (publicKey == null) { if (other.publicKey != null) { return false; } } else if (!publicKey.equals(other.publicKey)) { return false; } if (username == null) { if (other.username != null) { return false; } } else if (!username.equals(other.username)) { return false; } return true; } @Override public String toString() { return "User [username=" + username + ", firstName=" + firstName + ", middleName=" + middleName + ", lastName=" + lastName + ", displayName=" + displayName + ", email=" + email + ", publicKey=" + publicKey + "]"; } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/features/OrganizationApi.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.features; import java.util.Set; import jakarta.inject.Named; import jakarta.ws.rs.Consumes; import jakarta.ws.rs.DELETE; import jakarta.ws.rs.GET; import jakarta.ws.rs.POST; import jakarta.ws.rs.PUT; import jakarta.ws.rs.Path; import jakarta.ws.rs.PathParam; import jakarta.ws.rs.core.MediaType; import org.jclouds.Constants; import org.jclouds.Fallbacks.NullOnNotFoundOr404; import org.jclouds.chef.ChefApi; import org.jclouds.chef.binders.BindGroupToUpdateRequestJsonPayload; import org.jclouds.chef.binders.GroupName; import org.jclouds.chef.domain.Group; import org.jclouds.chef.domain.User; import org.jclouds.chef.filters.SignedHeaderAuth; import org.jclouds.chef.functions.ParseKeySetFromJson; import org.jclouds.rest.annotations.BinderParam; import org.jclouds.rest.annotations.Fallback; import org.jclouds.rest.annotations.Headers; import org.jclouds.rest.annotations.ParamParser; import org.jclouds.rest.annotations.RequestFilters; import org.jclouds.rest.annotations.ResponseParser; import org.jclouds.rest.annotations.SinceApiVersion; import org.jclouds.rest.annotations.WrapWith; /** * Provides synchronous access to the Enterprise Chef Api. */ @RequestFilters(SignedHeaderAuth.class) @Consumes(MediaType.APPLICATION_JSON) @Headers(keys = "X-Chef-Version", values = "{" + Constants.PROPERTY_API_VERSION + "}") @SinceApiVersion("12.0.0") public interface OrganizationApi extends ChefApi { /** * Retrieves an existing user. * * @param name * The name of the user to get. * @return The details of the user or null if not found. */ @Named("user:get") @GET @Path("/users/{name}") @Fallback(NullOnNotFoundOr404.class) User getUser(@PathParam("name") String name); /** * List all existing groups. * * @return The list of groups. */ @Named("group:list") @GET @Path("/groups") @ResponseParser(ParseKeySetFromJson.class) Set listGroups(); /** * Retrieves an existing group. * * @param name * The name of the group to get. * @return The details of the group or null if not found. */ @Named("group:get") @GET @Path("/groups/{name}") @Fallback(NullOnNotFoundOr404.class) Group getGroup(@PathParam("name") String name); /** * Creates a new group. * * @param name * The name of the group to create. */ @Named("group:create") @POST @Path("/groups") void createGroup(@WrapWith("groupname") String name); /** * Updates a group. *

* This method can be used to add actors (clients, groups) to the group. * * @param group * The group with the updated information. */ @Named("group:update") @PUT @Path("/groups/{name}") void updateGroup( @PathParam("name") @ParamParser(GroupName.class) @BinderParam(BindGroupToUpdateRequestJsonPayload.class) Group group); /** * Deletes a group. * * @param name * The name of the group to delete. */ @Named("group:delete") @DELETE @Path("/groups/{name}") void deleteGroup(@PathParam("name") String name); } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/filters/SignedHeaderAuth.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.filters; import static com.google.common.base.Charsets.UTF_8; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.hash.Hashing.sha1; import static com.google.common.io.BaseEncoding.base64; import java.io.IOException; import java.security.PrivateKey; import java.util.NoSuchElementException; import jakarta.annotation.Resource; import jakarta.inject.Inject; import jakarta.inject.Named; import jakarta.inject.Provider; import jakarta.inject.Singleton; import org.jclouds.Constants; import org.jclouds.crypto.Crypto; import org.jclouds.date.TimeStamp; import org.jclouds.domain.Credentials; import org.jclouds.http.HttpException; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequestFilter; import org.jclouds.http.HttpUtils; import org.jclouds.http.internal.SignatureWire; import org.jclouds.io.ByteStreams2; import org.jclouds.io.Payload; import org.jclouds.io.Payloads; import org.jclouds.io.payloads.MultipartForm; import org.jclouds.io.payloads.Part; import org.jclouds.io.payloads.RSAEncryptingPayload; import org.jclouds.logging.Logger; import org.jclouds.util.Strings2; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Predicate; import com.google.common.base.Splitter; import com.google.common.base.Supplier; import com.google.common.base.Throwables; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Iterables; import com.google.common.collect.Multimap; import com.google.common.io.ByteSource; /** * Ported from mixlib-authentication in order to sign Chef requests. * * @see */ @Singleton public class SignedHeaderAuth implements HttpRequestFilter { public static final String SIGNING_DESCRIPTION = "version=1.0"; private final SignatureWire signatureWire; private final Supplier creds; private final Supplier supplyKey; private final Provider timeStampProvider; private final String emptyStringHash; private final HttpUtils utils; private final Crypto crypto; @Resource @Named(Constants.LOGGER_SIGNATURE) Logger signatureLog = Logger.NULL; @Inject public SignedHeaderAuth(SignatureWire signatureWire, @org.jclouds.location.Provider Supplier creds, Supplier supplyKey, @TimeStamp Provider timeStampProvider, HttpUtils utils, Crypto crypto) { this.signatureWire = checkNotNull(signatureWire, "signatureWire"); this.creds = checkNotNull(creds, "creds"); this.supplyKey = checkNotNull(supplyKey, "supplyKey"); this.timeStampProvider = checkNotNull(timeStampProvider, "timeStampProvider"); this.emptyStringHash = hashBody(Payloads.newStringPayload("")); this.utils = checkNotNull(utils, "utils"); this.crypto = checkNotNull(crypto, "crypto"); } public HttpRequest filter(HttpRequest input) throws HttpException { HttpRequest request = input.toBuilder().endpoint(input.getEndpoint().toString().replace("%3F", "?")).build(); String contentHash = hashBody(request.getPayload()); Multimap headers = ArrayListMultimap.create(); headers.put("X-Ops-Content-Hash", contentHash); String timestamp = timeStampProvider.get(); String toSign = createStringToSign(request.getMethod(), hashPath(request.getEndpoint().getPath()), contentHash, timestamp); headers.put("X-Ops-Userid", creds.get().identity); headers.put("X-Ops-Sign", SIGNING_DESCRIPTION); request = calculateAndReplaceAuthorizationHeaders(request, toSign); headers.put("X-Ops-Timestamp", timestamp); utils.logRequest(signatureLog, request, "<<"); return request.toBuilder().replaceHeaders(headers).build(); } @VisibleForTesting HttpRequest calculateAndReplaceAuthorizationHeaders(HttpRequest request, String toSign) throws HttpException { String signature = sign(toSign); if (signatureWire.enabled()) signatureWire.input(Strings2.toInputStream(signature)); String[] signatureLines = Iterables.toArray(Splitter.fixedLength(60).split(signature), String.class); Multimap headers = ArrayListMultimap.create(); for (int i = 0; i < signatureLines.length; i++) { headers.put("X-Ops-Authorization-" + (i + 1), signatureLines[i]); } return request.toBuilder().replaceHeaders(headers).build(); } public String createStringToSign(String request, String hashedPath, String contentHash, String timestamp) { return new StringBuilder().append("Method:").append(request).append("\n").append("Hashed Path:") .append(hashedPath).append("\n").append("X-Ops-Content-Hash:").append(contentHash).append("\n") .append("X-Ops-Timestamp:").append(timestamp).append("\n").append("X-Ops-UserId:") .append(creds.get().identity).toString(); } @VisibleForTesting String hashPath(String path) { try { return base64().encode(ByteSource.wrap(canonicalPath(path).getBytes(UTF_8)).hash(sha1()).asBytes()); } catch (Exception e) { Throwables.propagateIfPossible(e); throw new HttpException("error creating sigature for path: " + path, e); } } /** * Build the canonicalized path, which collapses multiple slashes (/) and * removes a trailing slash unless the path is only "/" */ @VisibleForTesting String canonicalPath(String path) { path = path.replaceAll("\\/+", "/"); return path.endsWith("/") && path.length() > 1 ? path.substring(0, path.length() - 1) : path; } @VisibleForTesting String hashBody(Payload payload) { if (payload == null) return emptyStringHash; payload = useTheFilePartIfForm(payload); checkArgument(payload != null, "payload was null"); checkArgument(payload.isRepeatable(), "payload must be repeatable: " + payload); try { return base64().encode(ByteStreams2.hashAndClose(payload.getInput(), sha1()).asBytes()); } catch (Exception e) { Throwables.propagateIfPossible(e); throw new HttpException("error creating sigature for payload: " + payload, e); } } private Payload useTheFilePartIfForm(Payload payload) { if (payload instanceof MultipartForm) { Iterable parts = MultipartForm.class.cast(payload).getRawContent(); try { payload = Iterables.find(parts, new Predicate() { @Override public boolean apply(Part input) { return "file".equals(input.getName()); } }); } catch (NoSuchElementException e) { } } return payload; } public String sign(String toSign) { try { byte[] encrypted = ByteStreams2.toByteArrayAndClose(new RSAEncryptingPayload(crypto, Payloads.newStringPayload(toSign), supplyKey.get()).openStream()); return base64().encode(encrypted); } catch (IOException e) { throw new HttpException("error signing request", e); } } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/functions/BootstrapConfigForGroup.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.functions; import static com.google.common.base.Preconditions.checkState; import static org.jclouds.chef.config.ChefProperties.CHEF_BOOTSTRAP_DATABAG; import jakarta.inject.Inject; import jakarta.inject.Named; import jakarta.inject.Singleton; import org.jclouds.chef.ChefApi; import org.jclouds.chef.domain.BootstrapConfig; import org.jclouds.chef.domain.DatabagItem; import org.jclouds.json.Json; import com.google.common.base.Function; /** * Retrieves the bootstrap configuration for a specific group */ @Singleton public class BootstrapConfigForGroup implements Function { private final ChefApi api; private final String databag; private final Json json; @Inject BootstrapConfigForGroup(@Named(CHEF_BOOTSTRAP_DATABAG) String databag, ChefApi api, Json json) { this.databag = databag; this.api = api; this.json = json; } @Override public BootstrapConfig apply(String from) { DatabagItem bootstrapConfig = api.getDatabagItem(databag, from); checkState(bootstrapConfig != null, "databag item %s/%s not found", databag, from); // A DatabagItem is already a JsonBall, to we can easily deserialize it return json.fromJson(bootstrapConfig.toString(), BootstrapConfig.class); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/functions/ClientForGroup.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.functions; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.collect.Sets.newHashSet; import java.util.Set; import jakarta.inject.Inject; import jakarta.inject.Singleton; import org.jclouds.chef.ChefApi; import org.jclouds.chef.domain.Client; import com.google.common.base.Function; /** * * Generates a client relevant for a particular group */ @Singleton public class ClientForGroup implements Function { private final ChefApi chefApi; @Inject public ClientForGroup(ChefApi chefApi) { this.chefApi = checkNotNull(chefApi, "chefApi"); } @Override public Client apply(String from) { String clientName = findNextClientName(chefApi.listClients(), from + "-client-%02d"); Client client = chefApi.createClient(clientName); // response from create only includes the key return Client.builder() // .clientname(clientName) // .name(clientName) // .isValidator(false) // .privateKey(client.getPrivateKey()) // .build(); } private static String findNextClientName(Set clients, String pattern) { String clientName; Set names = newHashSet(clients); int index = 0; while (true) { clientName = String.format(pattern, index++); if (!names.contains(clientName)) break; } return clientName; } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/functions/GroupToBootScript.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.functions; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.collect.Iterables.transform; import static org.jclouds.scriptbuilder.domain.Statements.createOrOverwriteFile; import static org.jclouds.scriptbuilder.domain.Statements.exec; import java.net.URI; import java.security.PrivateKey; import java.util.Collections; import java.util.regex.Pattern; import jakarta.inject.Inject; import jakarta.inject.Singleton; import org.jclouds.chef.config.InstallChef; import org.jclouds.chef.config.Validator; import org.jclouds.chef.domain.BootstrapConfig; import org.jclouds.crypto.Pems; import org.jclouds.javax.annotation.Nullable; import org.jclouds.location.Provider; import org.jclouds.scriptbuilder.ExitInsteadOfReturn; import org.jclouds.scriptbuilder.domain.Statement; import org.jclouds.scriptbuilder.domain.StatementList; import com.google.common.base.Function; import com.google.common.base.Joiner; import com.google.common.base.Optional; import com.google.common.base.Splitter; import com.google.common.base.Supplier; import com.google.common.base.Throwables; import com.google.common.cache.CacheLoader; import com.google.common.collect.ImmutableList; /** * Generates a bootstrap script relevant for a particular group */ @Singleton public class GroupToBootScript { private static final Pattern newLinePattern = Pattern.compile("(\\r\\n)|(\\n)"); private final Supplier endpoint; private final CacheLoader bootstrapConfigForGroup; private final Statement installChef; private final Optional validatorName; private final Optional validatorCredential; @Inject GroupToBootScript(@Provider Supplier endpoint, CacheLoader bootstrapConfigForGroup, @InstallChef Statement installChef, @Validator Optional validatorName, @Validator Optional validatorCredential) { this.endpoint = endpoint; this.bootstrapConfigForGroup = bootstrapConfigForGroup; this.installChef = installChef; this.validatorName = validatorName; this.validatorCredential = validatorCredential; } public Statement apply(String group, @Nullable String nodeName) { BootstrapConfig config = null; try { config = bootstrapConfigForGroup.load(checkNotNull(group, "group")); } catch (Exception ex) { throw Throwables.propagate(ex); } String chefConfigDir = "{root}etc{fs}chef"; String chefBootFile = chefConfigDir + "{fs}first-boot.json"; ImmutableList.Builder statements = ImmutableList.builder(); statements.add(new ExitInsteadOfReturn(installChef)); statements.add(exec("{md} " + chefConfigDir)); if (config.getSslCAFile() != null) { statements.add(createOrOverwriteFile(chefConfigDir + "{fs}chef-server.crt", Splitter.on(newLinePattern).split(config.getSslCAFile()))); } statements.add(createClientRbFile(chefConfigDir + "{fs}client.rb", group, nodeName, config)); statements.add(createOrOverwriteFile(chefConfigDir + "{fs}validation.pem", Splitter.on(newLinePattern).split(Pems.pem(validatorCredential.get())))); statements.add(createAttributesFile(chefBootFile, config)); statements.add(exec("chef-client -j " + chefBootFile)); return new StatementList(statements.build()); } private Statement createClientRbFile(String clientRbFile, String group, String nodeName, BootstrapConfig config) { ImmutableList.Builder clientRb = ImmutableList.builder(); clientRb.add("require 'rubygems'"); clientRb.add("require 'ohai'"); clientRb.add("o = Ohai::System.new"); clientRb.add("o.all_plugins"); clientRb.add("node_name \"" + (nodeName != null ? nodeName + "\"" : group + "-\" + o[:ipaddress]")); clientRb.add("log_level :info"); clientRb.add("log_location STDOUT"); clientRb.add(String.format("validation_client_name \"%s\"", validatorName.get())); clientRb.add(String.format("chef_server_url \"%s\"", endpoint.get())); addIfPresent(clientRb, "environment", config.getEnvironment()); if (config.getSslCAFile() != null) { addIfPresent(clientRb, "ssl_ca_file", "/etc/chef/chef-server.crt"); } addIfPresent(clientRb, "ssl_ca_path", config.getSslCAPath()); addIfPresent(clientRb, "ssl_verify_mode", config.getSslVerifyMode()); addIfPresent(clientRb, "verify_api_cert", config.getVerifyApiCert()); return createOrOverwriteFile(clientRbFile, clientRb.build()); } private Statement createAttributesFile(String chefBootFile, BootstrapConfig config) { String runlist = Joiner.on(',').join(transform(config.getRunList(), new Function() { @Override public String apply(String input) { return "\"" + input + "\""; } })); StringBuilder sb = new StringBuilder(); sb.append("{"); if (config.getAttributes() != null) { String attributes = config.getAttributes().toString(); // Omit the opening and closing json characters sb.append(attributes.trim().substring(1, attributes.length() - 1)); sb.append(","); } sb.append("\"run_list\":[").append(runlist).append("]"); sb.append("}"); return createOrOverwriteFile(chefBootFile, Collections.singleton(sb.toString())); } private void addIfPresent(ImmutableList.Builder lines, String key, Object value) { if (value != null) { // Quote the value if it is a String lines.add(String.format("%s %s", key, value instanceof String ? "\"" + value + "\"" : value.toString())); } } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/functions/ParseCookbookDefinitionFromJson.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.functions; import com.google.common.base.Function; import org.jclouds.chef.domain.CookbookDefinition; import org.jclouds.http.HttpResponse; import org.jclouds.http.functions.ParseJson; import jakarta.inject.Inject; import jakarta.inject.Singleton; import java.util.Map; /** * Parses the cookbook versions in a Chef Server >= 0.10.8. */ @Singleton public class ParseCookbookDefinitionFromJson implements Function { /** Parser for responses from chef server >= 0.10.8 */ private final ParseJson> parser; @Inject ParseCookbookDefinitionFromJson(ParseJson> parser) { this.parser = parser; } @Override public CookbookDefinition apply(HttpResponse response) { Map result = parser.apply(response); String cookbookName = result.keySet().iterator().next(); CookbookDefinition def = result.values().iterator().next(); return CookbookDefinition.builder() // .from(def) // .name(cookbookName) // .build(); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/functions/ParseCookbookDefinitionListFromJson.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.functions; import com.google.common.base.Function; import org.jclouds.chef.domain.CookbookDefinition; import org.jclouds.http.HttpResponse; import org.jclouds.http.functions.ParseJson; import jakarta.inject.Inject; import jakarta.inject.Singleton; import java.util.Map; import java.util.Set; import static com.google.common.collect.Iterables.transform; import static com.google.common.collect.Sets.newLinkedHashSet; /** * Parses the cookbook versions in a Chef Server >= 0.10.8. */ @Singleton public class ParseCookbookDefinitionListFromJson implements Function> { /** * Parser for responses from chef server >= 0.10.8 */ private final ParseJson> parser; @Inject ParseCookbookDefinitionListFromJson(ParseJson> parser) { this.parser = parser; } @Override public Set apply(HttpResponse response) { Set> result = parser.apply(response).entrySet(); return newLinkedHashSet(transform(result, new Function, CookbookDefinition>() { @Override public CookbookDefinition apply(Map.Entry input) { String cookbookName = input.getKey(); CookbookDefinition def = input.getValue(); return CookbookDefinition.builder() // .from(def) // .name(cookbookName) // .build(); } })); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/functions/ParseCookbookNamesFromJson.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.functions; import java.util.Map; import java.util.Set; import jakarta.inject.Inject; import jakarta.inject.Singleton; import org.jclouds.chef.domain.CookbookDefinition; import org.jclouds.http.HttpResponse; import org.jclouds.http.functions.ParseJson; import com.google.common.base.Function; /** * Parses a cookbook definition from a Json response, assuming a Chef Server >= * 0.10.8. */ @Singleton public class ParseCookbookNamesFromJson implements Function> { /** Parser for responses from chef server >= 0.10.8 */ private final ParseJson> parser; @Inject ParseCookbookNamesFromJson(ParseJson> parser) { this.parser = parser; } @Override public Set apply(HttpResponse response) { return parser.apply(response).keySet(); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/functions/ParseCookbookVersionsFromJson.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.functions; import java.util.Map; import java.util.Set; import jakarta.inject.Inject; import jakarta.inject.Singleton; import org.jclouds.chef.domain.CookbookDefinition; import org.jclouds.chef.domain.CookbookDefinition.Version; import org.jclouds.http.HttpResponse; import org.jclouds.http.functions.ParseJson; import com.google.common.base.Function; import static com.google.common.collect.Iterables.getFirst; import static com.google.common.collect.Iterables.transform; import static com.google.common.collect.Sets.newLinkedHashSet; /** * Parses the cookbook versions in a Chef Server >= 0.10.8. */ @Singleton public class ParseCookbookVersionsFromJson implements Function> { /** Parser for responses from chef server >= 0.10.8 */ private final ParseJson> parser; @Inject ParseCookbookVersionsFromJson(ParseJson> parser) { this.parser = parser; } @Override public Set apply(HttpResponse response) { CookbookDefinition def = getFirst(parser.apply(response).values(), null); return newLinkedHashSet(transform(def.getVersions(), new Function() { @Override public String apply(Version input) { return input.getVersion(); } })); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/functions/ParseErrorFromJsonOrReturnBody.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.functions; import java.util.regex.Matcher; import java.util.regex.Pattern; import jakarta.inject.Inject; import jakarta.inject.Singleton; import org.jclouds.http.HttpResponse; import org.jclouds.http.functions.ReturnStringIf2xx; import com.google.common.base.Function; @Singleton public class ParseErrorFromJsonOrReturnBody implements Function { Pattern pattern = Pattern.compile(".*\\[\"([^\"]+)\"\\].*"); private final ReturnStringIf2xx returnStringIf200; @Inject ParseErrorFromJsonOrReturnBody(ReturnStringIf2xx returnStringIf200) { this.returnStringIf200 = returnStringIf200; } @Override public String apply(HttpResponse response) { String content = returnStringIf200.apply(response); if (content == null) return null; return parse(content); } public String parse(String in) { Matcher matcher = pattern.matcher(in); if (matcher.find()) { return matcher.group(1); } return in; } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/functions/ParseKeySetFromJson.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.functions; import java.util.Map; import java.util.Set; import jakarta.inject.Inject; import jakarta.inject.Singleton; import org.jclouds.http.HttpResponse; import org.jclouds.http.functions.ParseJson; import com.google.common.base.Function; @Singleton public class ParseKeySetFromJson implements Function> { private final ParseJson> json; @Inject ParseKeySetFromJson(ParseJson> json) { this.json = json; } @Override public Set apply(HttpResponse response) { return json.apply(response).keySet(); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/functions/ParseSearchClientsFromJson.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.functions; import jakarta.inject.Inject; import jakarta.inject.Singleton; import org.jclouds.chef.domain.Client; import org.jclouds.http.functions.ParseJson; @Singleton public class ParseSearchClientsFromJson extends ParseSearchResultFromJson { // TODO add generic json parser detector @Inject ParseSearchClientsFromJson(ParseJson> json) { super(json); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/functions/ParseSearchDatabagFromJson.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.functions; import java.util.List; import jakarta.inject.Inject; import jakarta.inject.Singleton; import org.jclouds.chef.domain.DatabagItem; import org.jclouds.chef.domain.SearchResult; import org.jclouds.domain.JsonBall; import org.jclouds.http.HttpResponse; import org.jclouds.http.functions.ParseJson; import org.jclouds.json.Json; import com.google.common.base.Function; import com.google.gson.annotations.SerializedName; import static com.google.common.collect.Iterables.transform; /** * Parses the search result into a {@link DatabagItem} object. *

* When searching databags, the items are contained inside the * raw_data list. */ @Singleton public class ParseSearchDatabagFromJson implements Function> { private final ParseJson responseParser; private final Json json; static class Row { @SerializedName("raw_data") JsonBall rawData; } static class Response { long start; List rows; } @Inject ParseSearchDatabagFromJson(ParseJson responseParser, Json json) { this.responseParser = responseParser; this.json = json; } @Override public SearchResult apply(HttpResponse response) { Response returnVal = responseParser.apply(response); Iterable items = transform(returnVal.rows, new Function() { @Override public DatabagItem apply(Row input) { return json.fromJson(input.rawData.toString(), DatabagItem.class); } }); return new SearchResult(returnVal.start, items); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/functions/ParseSearchEnvironmentsFromJson.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.functions; import org.jclouds.chef.domain.Environment; import org.jclouds.http.functions.ParseJson; import jakarta.inject.Inject; import jakarta.inject.Singleton; @Singleton public class ParseSearchEnvironmentsFromJson extends ParseSearchResultFromJson { // TODO add generic json parser detector @Inject ParseSearchEnvironmentsFromJson(ParseJson> json) { super(json); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/functions/ParseSearchNodesFromJson.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.functions; import jakarta.inject.Inject; import jakarta.inject.Singleton; import org.jclouds.chef.domain.Node; import org.jclouds.http.functions.ParseJson; @Singleton public class ParseSearchNodesFromJson extends ParseSearchResultFromJson { // TODO add generic json parser detector @Inject ParseSearchNodesFromJson(ParseJson> json) { super(json); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/functions/ParseSearchResultFromJson.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.functions; import java.util.List; import jakarta.inject.Inject; import jakarta.inject.Singleton; import org.jclouds.chef.domain.SearchResult; import org.jclouds.http.HttpResponse; import org.jclouds.http.functions.ParseJson; import com.google.common.base.Function; @Singleton public class ParseSearchResultFromJson implements Function> { private final ParseJson> json; static class Response { long start; List rows; } @Inject ParseSearchResultFromJson(ParseJson> json) { this.json = json; } @Override public SearchResult apply(HttpResponse response) { Response returnVal = json.apply(response); return new SearchResult(returnVal.start, returnVal.rows); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/functions/ParseSearchRolesFromJson.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.functions; import jakarta.inject.Inject; import jakarta.inject.Singleton; import org.jclouds.chef.domain.Role; import org.jclouds.http.functions.ParseJson; @Singleton public class ParseSearchRolesFromJson extends ParseSearchResultFromJson { // TODO add generic json parser detector @Inject ParseSearchRolesFromJson(ParseJson> json) { super(json); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/functions/UriForResource.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.functions; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import java.net.URI; import jakarta.inject.Singleton; import org.jclouds.chef.domain.Resource; import com.google.common.base.Function; /** * Extracts the uri field of the given {@link Resource}. */ @Singleton public class UriForResource implements Function { @Override public URI apply(Object input) { checkArgument(checkNotNull(input, "input") instanceof Resource, "This function can only be applied to Resource objects"); return ((Resource) input).getUrl(); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/handlers/ChefApiErrorRetryHandler.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.handlers; import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream; import jakarta.annotation.Resource; import jakarta.inject.Named; import org.jclouds.Constants; import org.jclouds.http.HttpCommand; import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpRetryHandler; import org.jclouds.http.handlers.BackoffLimitedRetryHandler; import org.jclouds.logging.Logger; import com.google.inject.Inject; /** * Allow for eventual consistency on sandbox requests. */ public class ChefApiErrorRetryHandler implements HttpRetryHandler { @Inject(optional = true) @Named(Constants.PROPERTY_MAX_RETRIES) private int retryCountLimit = 5; @Resource protected Logger logger = Logger.NULL; private final BackoffLimitedRetryHandler backoffLimitedRetryHandler; @Inject ChefApiErrorRetryHandler(BackoffLimitedRetryHandler backoffLimitedRetryHandler) { this.backoffLimitedRetryHandler = backoffLimitedRetryHandler; } public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) { if (command.getFailureCount() > retryCountLimit) return false; if (response.getStatusCode() == 400 && command.getCurrentRequest().getMethod().equals("PUT") && command.getCurrentRequest().getEndpoint().getPath().indexOf("sandboxes") != -1) { if (response.getPayload() != null) { String error = new String(closeClientButKeepContentStream(response)); if (error != null && error.indexOf("was not uploaded") != -1) { return backoffLimitedRetryHandler.shouldRetryRequest(command, response); } } } return false; } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/handlers/ChefErrorHandler.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.handlers; import static org.jclouds.util.Closeables2.closeQuietly; import jakarta.annotation.Resource; import jakarta.inject.Inject; import jakarta.inject.Singleton; import org.jclouds.chef.functions.ParseErrorFromJsonOrReturnBody; import org.jclouds.http.HttpCommand; import org.jclouds.http.HttpErrorHandler; import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponseException; import org.jclouds.logging.Logger; import org.jclouds.rest.AuthorizationException; import org.jclouds.rest.ResourceNotFoundException; /** * This will parse and set an appropriate exception on the command object. */ @Singleton public class ChefErrorHandler implements HttpErrorHandler { @Resource protected Logger logger = Logger.NULL; private final ParseErrorFromJsonOrReturnBody errorParser; @Inject ChefErrorHandler(ParseErrorFromJsonOrReturnBody errorParser) { this.errorParser = errorParser; } public void handleError(HttpCommand command, HttpResponse response) { String message = errorParser.apply(response); Exception exception = new HttpResponseException(command, response, message); try { message = message != null ? message : String.format("%s -> %s", command.getCurrentRequest().getRequestLine(), response.getStatusLine()); switch (response.getStatusCode()) { case 401: case 403: exception = new AuthorizationException(message, exception); break; case 404: if (!command.getCurrentRequest().getMethod().equals("DELETE")) { exception = new ResourceNotFoundException(message, exception); } break; } } finally { closeQuietly(response.getPayload()); command.setException(exception); } } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/internal/BaseChefService.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.internal; import static com.google.common.base.Preconditions.checkNotNull; import static org.jclouds.chef.config.ChefProperties.CHEF_BOOTSTRAP_DATABAG; import java.io.IOException; import java.io.InputStream; import java.security.PrivateKey; import java.util.concurrent.ExecutorService; import jakarta.annotation.Resource; import jakarta.inject.Inject; import jakarta.inject.Named; import jakarta.inject.Singleton; import org.jclouds.chef.ChefApi; import org.jclouds.chef.ChefService; import org.jclouds.chef.config.ChefProperties; import org.jclouds.chef.domain.BootstrapConfig; import org.jclouds.chef.domain.Client; import org.jclouds.chef.domain.CookbookVersion; import org.jclouds.chef.domain.DatabagItem; import org.jclouds.chef.domain.Environment; import org.jclouds.chef.domain.Node; import org.jclouds.chef.functions.BootstrapConfigForGroup; import org.jclouds.chef.functions.GroupToBootScript; import org.jclouds.chef.strategy.CleanupStaleNodesAndClients; import org.jclouds.chef.strategy.CreateNodeAndPopulateAutomaticAttributes; import org.jclouds.chef.strategy.DeleteAllClientsInList; import org.jclouds.chef.strategy.DeleteAllNodesInList; import org.jclouds.chef.strategy.ListClients; import org.jclouds.chef.strategy.ListCookbookVersions; import org.jclouds.chef.strategy.ListCookbookVersionsInEnvironment; import org.jclouds.chef.strategy.ListEnvironments; import org.jclouds.chef.strategy.ListNodes; import org.jclouds.chef.strategy.ListNodesInEnvironment; import org.jclouds.chef.strategy.UpdateAutomaticAttributesOnNode; import org.jclouds.crypto.Crypto; import org.jclouds.io.ByteStreams2; import org.jclouds.io.Payload; import org.jclouds.io.Payloads; import org.jclouds.io.payloads.RSADecryptingPayload; import org.jclouds.io.payloads.RSAEncryptingPayload; import org.jclouds.javax.annotation.Nullable; import org.jclouds.json.Json; import org.jclouds.logging.Logger; import org.jclouds.scriptbuilder.domain.Statement; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Supplier; @Singleton public class BaseChefService implements ChefService { private final ChefApi api; private final CleanupStaleNodesAndClients cleanupStaleNodesAndClients; private final CreateNodeAndPopulateAutomaticAttributes createNodeAndPopulateAutomaticAttributes; private final DeleteAllNodesInList deleteAllNodesInList; private final ListNodes listNodes; private final DeleteAllClientsInList deleteAllClientsInList; private final ListClients listClients; private final UpdateAutomaticAttributesOnNode updateAutomaticAttributesOnNode; private final Supplier privateKey; private final GroupToBootScript groupToBootScript; private final String databag; private final BootstrapConfigForGroup bootstrapConfigForGroup; private final ListCookbookVersions listCookbookVersions; private final ListCookbookVersionsInEnvironment listCookbookVersionsInEnvironment; private final ListEnvironments listEnvironments; private final ListNodesInEnvironment listNodesInEnvironment; private final Json json; private final Crypto crypto; @Resource @Named(ChefProperties.CHEF_LOGGER) protected Logger logger = Logger.NULL; @Inject BaseChefService(ChefApi api, CleanupStaleNodesAndClients cleanupStaleNodesAndClients, CreateNodeAndPopulateAutomaticAttributes createNodeAndPopulateAutomaticAttributes, DeleteAllNodesInList deleteAllNodesInList, ListNodes listNodes, DeleteAllClientsInList deleteAllClientsInList, ListClients listClients, ListCookbookVersions listCookbookVersions, UpdateAutomaticAttributesOnNode updateAutomaticAttributesOnNode, Supplier privateKey, @Named(CHEF_BOOTSTRAP_DATABAG) String databag, GroupToBootScript groupToBootScript, BootstrapConfigForGroup bootstrapConfigForGroup, ListEnvironments listEnvironments, ListNodesInEnvironment listNodesInEnvironment, ListCookbookVersionsInEnvironment listCookbookVersionsInEnvironment, Json json, Crypto crypto) { this.api = api; this.cleanupStaleNodesAndClients = cleanupStaleNodesAndClients; this.createNodeAndPopulateAutomaticAttributes = createNodeAndPopulateAutomaticAttributes; this.deleteAllNodesInList = deleteAllNodesInList; this.listNodes = listNodes; this.deleteAllClientsInList = deleteAllClientsInList; this.listClients = listClients; this.listCookbookVersions = listCookbookVersions; this.updateAutomaticAttributesOnNode = updateAutomaticAttributesOnNode; this.privateKey = privateKey; this.groupToBootScript = groupToBootScript; this.databag = databag; this.bootstrapConfigForGroup = bootstrapConfigForGroup; this.listEnvironments = listEnvironments; this.listNodesInEnvironment = listNodesInEnvironment; this.listCookbookVersionsInEnvironment = listCookbookVersionsInEnvironment; this.json = json; this.crypto = crypto; } @Override public byte[] encrypt(InputStream input) throws IOException { @SuppressWarnings("resource") Payload payload = new RSAEncryptingPayload(crypto, Payloads.newPayload(input), privateKey.get()); return ByteStreams2.toByteArrayAndClose(payload.openStream()); } @Override public byte[] decrypt(InputStream input) throws IOException { @SuppressWarnings("resource") Payload payload = new RSADecryptingPayload(crypto, Payloads.newPayload(input), privateKey.get()); return ByteStreams2.toByteArrayAndClose(payload.openStream()); } @Override public Statement createBootstrapScriptForGroup(String group, @Nullable String nodeName) { return groupToBootScript.apply(group, nodeName); } @Override public Statement createBootstrapScriptForGroup(String group) { return groupToBootScript.apply(group, null); } @Override public void updateBootstrapConfigForGroup(String group, BootstrapConfig bootstrapConfig) { checkNotNull(bootstrapConfig, "bootstrapConfig cannot be null"); try { api.createDatabag(databag); } catch (IllegalStateException e) { } String jsonConfig = buildBootstrapConfiguration(bootstrapConfig); DatabagItem config = new DatabagItem(group, jsonConfig); if (api.getDatabagItem(databag, group) == null) { api.createDatabagItem(databag, config); } else { api.updateDatabagItem(databag, config); } } @VisibleForTesting String buildBootstrapConfiguration(BootstrapConfig config) { return json.toJson(config); } @Override public BootstrapConfig getBootstrapConfigForGroup(String group) { return bootstrapConfigForGroup.apply(group); } @Override public void cleanupStaleNodesAndClients(String prefix, int secondsStale) { cleanupStaleNodesAndClients.execute(prefix, secondsStale); } @Override public Node createNodeAndPopulateAutomaticAttributes(String nodeName, Iterable runList) { return createNodeAndPopulateAutomaticAttributes.execute(nodeName, runList); } @Override public void updateAutomaticAttributesOnNode(String nodeName) { updateAutomaticAttributesOnNode.execute(nodeName); } @Override public void deleteAllNodesInList(Iterable names) { deleteAllNodesInList.execute(names); } @Override public void deleteAllClientsInList(Iterable names) { deleteAllClientsInList.execute(names); } @Override public Iterable listNodes() { return listNodes.execute(); } @Override public Iterable listNodes(ExecutorService executorService) { return listNodes.execute(executorService); } @Override public Iterable listClients() { return listClients.execute(); } @Override public Iterable listClients(ExecutorService executorService) { return listClients.execute(executorService); } @Override public Iterable listCookbookVersions() { return listCookbookVersions.execute(); } @Override public Iterable listCookbookVersions(ExecutorService executorService) { return listCookbookVersions.execute(executorService); } @Override public Iterable listCookbookVersionsInEnvironment(String environmentName) { return listCookbookVersionsInEnvironment.execute(environmentName); } @Override public Iterable listCookbookVersionsInEnvironment(String environmentName, ExecutorService executorService) { return listCookbookVersionsInEnvironment.execute(executorService, environmentName); } @Override public Iterable listCookbookVersionsInEnvironment(String environmentName, String numVersions) { return listCookbookVersionsInEnvironment.execute(environmentName, numVersions); } @Override public Iterable listCookbookVersionsInEnvironment(String environmentName, String numVersions, ExecutorService executorService) { return listCookbookVersionsInEnvironment.execute(executorService, environmentName, numVersions); } @Override public Iterable listEnvironments() { return listEnvironments.execute(); } @Override public Iterable listNodesInEnvironment(String environmentName) { return listNodesInEnvironment.execute(environmentName); } @Override public Iterable listNodesInEnvironment(String environmentName, ExecutorService executorService) { return listNodesInEnvironment.execute(executorService, environmentName); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/options/CreateClientOptions.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.options; /** * Options for the create client method. */ public class CreateClientOptions implements Cloneable { /** Administrator flag. This flag will be ignored in Chef 12. */ private boolean admin; public CreateClientOptions() { } CreateClientOptions(final boolean admin) { super(); this.admin = admin; } public boolean isAdmin() { return admin; } public CreateClientOptions admin() { this.admin = true; return this; } @Override protected Object clone() throws CloneNotSupportedException { return new CreateClientOptions(admin); } @Override public String toString() { return "[admin=" + admin + "]"; } public static class Builder { /** * @see CreateClientOptions#admin() */ public static CreateClientOptions admin() { CreateClientOptions options = new CreateClientOptions(); return options.admin(); } } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/options/SearchOptions.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.options; import static com.google.common.base.Preconditions.checkNotNull; import org.jclouds.http.options.BaseHttpRequestOptions; /** * Options for the search api. */ public class SearchOptions extends BaseHttpRequestOptions { /** * A valid search string. */ public SearchOptions query(String query) { this.queryParameters.put("q", checkNotNull(query, "query")); return this; } /** * A sort string, such as 'name DESC'. */ public SearchOptions sort(String sort) { this.queryParameters.put("sort", checkNotNull(sort, "sort")); return this; } /** * The number of rows to return. */ public SearchOptions rows(int rows) { this.queryParameters.put("rows", String.valueOf(rows)); return this; } /** * The result number to start from. */ public SearchOptions start(int start) { this.queryParameters.put("start", String.valueOf(start)); return this; } public static class Builder { /** * @see SearchOptions#query(String) */ public static SearchOptions query(String query) { SearchOptions options = new SearchOptions(); return options.query(query); } /** * @see SearchOptions#sort(String) */ public static SearchOptions start(String start) { SearchOptions options = new SearchOptions(); return options.sort(start); } /** * @see SearchOptions#rows(int) */ public static SearchOptions rows(int rows) { SearchOptions options = new SearchOptions(); return options.rows(rows); } /** * @see SearchOptions#start(int) */ public static SearchOptions start(int start) { SearchOptions options = new SearchOptions(); return options.start(start); } } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/predicates/CookbookVersionPredicates.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.predicates; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.collect.Iterables.any; import static com.google.common.collect.Iterables.get; import org.jclouds.chef.domain.CookbookVersion; import org.jclouds.chef.domain.Resource; import com.google.common.base.Predicate; import com.google.common.base.Splitter; import com.google.common.collect.LinkedListMultimap; import com.google.common.collect.Multimap; /** * Container for cookbook filters (predicates). * * This class has static methods that create customized predicates to use with * {@link org.jclouds.chef.ChefService}. */ public class CookbookVersionPredicates { /** * @see #containsRecipes */ public static Predicate containsRecipe(String recipe) { return containsRecipes(checkNotNull(recipe, "recipe must be defined")); } /** * Note that the default recipe of a cookbook is its name. Otherwise, you * prefix the recipe with the name of the cookbook. ex. {@code apache2} will * be the default recipe where {@code apache2::mod_proxy} is a specific one * in the cookbook. * * @param recipes * names of the recipes. * @return true if the cookbook version contains a recipe in the list. */ public static Predicate containsRecipes(String... recipes) { checkNotNull(recipes, "recipes must be defined"); final Multimap search = LinkedListMultimap.create(); for (String recipe : recipes) { if (recipe.indexOf("::") != -1) { Iterable nameRecipe = Splitter.on("::").split(recipe); search.put(get(nameRecipe, 0), get(nameRecipe, 1) + ".rb"); } else { search.put(recipe, "default.rb"); } } return new Predicate() { @Override public boolean apply(final CookbookVersion cookbookVersion) { return search.containsKey(cookbookVersion.getCookbookName()) && any(search.get(cookbookVersion.getCookbookName()), new Predicate() { @Override public boolean apply(final String recipeName) { return any(cookbookVersion.getRecipes(), new Predicate() { @Override public boolean apply(Resource resource) { return resource.getName().equals(recipeName); } }); } }); } @Override public String toString() { return "containsRecipes(" + search + ")"; } }; } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/strategy/CleanupStaleNodesAndClients.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.strategy; import org.jclouds.chef.strategy.internal.CleanupStaleNodesAndClientsImpl; import com.google.inject.ImplementedBy; /** * * Cleans up nodes and clients who have been hanging around too long. */ @ImplementedBy(CleanupStaleNodesAndClientsImpl.class) public interface CleanupStaleNodesAndClients { void execute(String prefix, int secondsStale); } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/strategy/CreateNodeAndPopulateAutomaticAttributes.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.strategy; import org.jclouds.chef.domain.Node; import org.jclouds.chef.strategy.internal.CreateNodeAndPopulateAutomaticAttributesImpl; import com.google.inject.ImplementedBy; /** * * Creates a new node with automatic attributes. */ @ImplementedBy(CreateNodeAndPopulateAutomaticAttributesImpl.class) public interface CreateNodeAndPopulateAutomaticAttributes { Node execute(Node node); Node execute(String nodeName, Iterable runList); } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/strategy/DeleteAllClientsInList.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.strategy; import org.jclouds.chef.strategy.internal.DeleteAllClientsInListImpl; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.inject.ImplementedBy; /** * Deletes all clients in a given list. */ @ImplementedBy(DeleteAllClientsInListImpl.class) public interface DeleteAllClientsInList { void execute(Iterable names); void execute(ListeningExecutorService executor, Iterable names); } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/strategy/DeleteAllNodesInList.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.strategy; import org.jclouds.chef.strategy.internal.DeleteAllNodesInListImpl; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.inject.ImplementedBy; @ImplementedBy(DeleteAllNodesInListImpl.class) public interface DeleteAllNodesInList { void execute(Iterable names); void execute(ListeningExecutorService executor, Iterable names); } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/strategy/ListClients.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.strategy; import com.google.inject.ImplementedBy; import org.jclouds.chef.domain.Client; import org.jclouds.chef.strategy.internal.ListClientsImpl; import java.util.concurrent.ExecutorService; @ImplementedBy(ListClientsImpl.class) public interface ListClients { Iterable execute(); Iterable execute(ExecutorService executor); } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/strategy/ListCookbookVersions.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.strategy; import com.google.inject.ImplementedBy; import org.jclouds.chef.domain.CookbookVersion; import org.jclouds.chef.strategy.internal.ListCookbookVersionsImpl; import java.util.concurrent.ExecutorService; @ImplementedBy(ListCookbookVersionsImpl.class) public interface ListCookbookVersions { Iterable execute(); Iterable execute(ExecutorService executor); } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/strategy/ListCookbookVersionsInEnvironment.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.strategy; import com.google.inject.ImplementedBy; import org.jclouds.chef.domain.CookbookVersion; import org.jclouds.chef.strategy.internal.ListCookbookVersionsInEnvironmentImpl; import java.util.concurrent.ExecutorService; @ImplementedBy(ListCookbookVersionsInEnvironmentImpl.class) public interface ListCookbookVersionsInEnvironment { Iterable execute(String environmentName); Iterable execute(String environmentName, String numVersions); Iterable execute(ExecutorService executor, String environmentName); Iterable execute(ExecutorService executor, String environmentName, String numVersions); } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/strategy/ListEnvironments.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.strategy; import com.google.inject.ImplementedBy; import org.jclouds.chef.domain.Environment; import org.jclouds.chef.strategy.internal.ListEnvironmentsImpl; import java.util.concurrent.ExecutorService; @ImplementedBy(ListEnvironmentsImpl.class) public interface ListEnvironments { Iterable execute(); Iterable execute(ExecutorService executor); } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/strategy/ListNodes.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.strategy; import com.google.inject.ImplementedBy; import org.jclouds.chef.domain.Node; import org.jclouds.chef.strategy.internal.ListNodesImpl; import java.util.concurrent.ExecutorService; @ImplementedBy(ListNodesImpl.class) public interface ListNodes { Iterable execute(); Iterable execute(ExecutorService executor); } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/strategy/ListNodesInEnvironment.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.strategy; import com.google.inject.ImplementedBy; import org.jclouds.chef.domain.Node; import org.jclouds.chef.strategy.internal.ListNodesInEnvironmentImpl; import java.util.concurrent.ExecutorService; @ImplementedBy(ListNodesInEnvironmentImpl.class) public interface ListNodesInEnvironment { Iterable execute(String environmentName); Iterable execute(ExecutorService executor, String environmentName); } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/strategy/UpdateAutomaticAttributesOnNode.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.strategy; import org.jclouds.chef.strategy.internal.UpdateAutomaticAttributesOnNodeImpl; import com.google.inject.ImplementedBy; /** * * Updates node with new automatic attributes. */ @ImplementedBy(UpdateAutomaticAttributesOnNodeImpl.class) public interface UpdateAutomaticAttributesOnNode { void execute(String nodeName); } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/strategy/internal/BaseListCookbookVersionsImpl.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.strategy.internal; import com.google.common.base.Function; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListeningExecutorService; import org.jclouds.chef.ChefApi; import org.jclouds.chef.domain.CookbookVersion; import org.jclouds.logging.Logger; import java.util.List; import java.util.Set; import java.util.concurrent.Callable; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.collect.Iterables.concat; import static com.google.common.collect.Iterables.transform; import static com.google.common.util.concurrent.Futures.allAsList; import static com.google.common.util.concurrent.Futures.getUnchecked; public abstract class BaseListCookbookVersionsImpl { protected final ChefApi api; protected Logger logger = Logger.NULL; BaseListCookbookVersionsImpl(ChefApi api) { this.api = checkNotNull(api, "api"); } protected Iterable execute(Iterable toGet) { return concat(transform(toGet, new Function>() { @Override public Iterable apply(final String cookbook) { // TODO getting each version could also go parallel Set cookbookVersions = api.listVersionsOfCookbook(cookbook); Iterable cookbooksVersions = transform(cookbookVersions, new Function() { @Override public CookbookVersion apply(final String version) { return api.getCookbook(cookbook, version); } } ); logger.trace(String.format("getting versions of cookbook: %s", cookbook)); return cookbooksVersions; } })); } protected Iterable executeConcurrently(final ListeningExecutorService executor, Iterable cookbookNames) { return concat(transform(cookbookNames, new Function>() { @Override public Iterable apply(final String cookbook) { // TODO getting each version could also go parallel Set cookbookVersions = api.listVersionsOfCookbook(cookbook); ListenableFuture> futures = allAsList(transform(cookbookVersions, new Function>() { @Override public ListenableFuture apply(final String version) { return executor.submit(new Callable() { @Override public CookbookVersion call() throws Exception { return api.getCookbook(cookbook, version); } }); } } )); logger.trace(String.format("getting versions of cookbook: %s", cookbook)); return getUnchecked(futures); } })); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/strategy/internal/BaseListNodesImpl.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.strategy.internal; import com.google.common.base.Function; import com.google.common.base.Joiner; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListeningExecutorService; import org.jclouds.chef.ChefApi; import org.jclouds.chef.domain.Node; import org.jclouds.logging.Logger; import java.util.List; import java.util.concurrent.Callable; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.collect.Iterables.transform; import static com.google.common.util.concurrent.Futures.allAsList; import static com.google.common.util.concurrent.Futures.getUnchecked; public abstract class BaseListNodesImpl { protected final ChefApi api; protected Logger logger = Logger.NULL; BaseListNodesImpl(ChefApi api) { this.api = checkNotNull(api, "api"); } protected Iterable execute(Iterable toGet) { Iterable nodes = transform(toGet, new Function() { @Override public Node apply(final String input) { return api.getNode(input); } } ); logger.trace(String.format("getting nodes: %s", Joiner.on(',').join(toGet))); return nodes; } protected Iterable executeConcurrently(final ListeningExecutorService executor, Iterable toGet) { ListenableFuture> futures = allAsList(transform(toGet, new Function>() { @Override public ListenableFuture apply(final String input) { return executor.submit(new Callable() { @Override public Node call() throws Exception { return api.getNode(input); } }); } })); logger.trace(String.format("getting nodes: %s", Joiner.on(',').join(toGet))); return getUnchecked(futures); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/strategy/internal/CleanupStaleNodesAndClientsImpl.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.strategy.internal; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Predicates.and; import static com.google.common.base.Predicates.notNull; import static com.google.common.collect.Iterables.filter; import static com.google.common.collect.Iterables.transform; import static org.jclouds.chef.util.ChefUtils.fromOhaiTime; import java.util.Calendar; import java.util.Date; import jakarta.annotation.Resource; import jakarta.inject.Inject; import jakarta.inject.Named; import jakarta.inject.Singleton; import org.jclouds.chef.config.ChefProperties; import org.jclouds.chef.domain.Node; import org.jclouds.chef.strategy.CleanupStaleNodesAndClients; import org.jclouds.chef.strategy.DeleteAllClientsInList; import org.jclouds.chef.strategy.DeleteAllNodesInList; import org.jclouds.chef.strategy.ListNodes; import org.jclouds.domain.JsonBall; import org.jclouds.logging.Logger; import com.google.common.base.Function; import com.google.common.base.Predicate; /** * * Cleans up nodes and apis who have been hanging around too long. */ @Singleton public class CleanupStaleNodesAndClientsImpl implements CleanupStaleNodesAndClients { @Resource @Named(ChefProperties.CHEF_LOGGER) protected Logger logger = Logger.NULL; private final ListNodes nodeLister; private final DeleteAllNodesInList nodeDeleter; private final DeleteAllClientsInList clientDeleter; @Inject public CleanupStaleNodesAndClientsImpl(DeleteAllNodesInList nodeDeleter, DeleteAllClientsInList clientDeleter, ListNodes nodeLister) { this.nodeLister = checkNotNull(nodeLister, "nodeLister"); this.nodeDeleter = checkNotNull(nodeDeleter, "nodeDeleter"); this.clientDeleter = checkNotNull(clientDeleter, "clientDeleter"); } @Override public void execute(final String prefix, int secondsStale) { final Calendar expired = Calendar.getInstance(); expired.setTime(new Date()); expired.add(Calendar.SECOND, -secondsStale); Iterable staleNodes = filter( nodeLister.execute(), and(notNull(), new Predicate() { @Override public boolean apply(Node input) { return input.getName().startsWith(prefix); } }, new Predicate() { @Override public boolean apply(Node input) { JsonBall dateLong = input.getAutomaticAttributes().get("ohai_time"); if (dateLong == null) return true; Calendar nodeUpdate = Calendar.getInstance(); nodeUpdate.setTime(fromOhaiTime(dateLong)); return expired.after(nodeUpdate); } })); Iterable nodeNames = transform(staleNodes, new Function() { @Override public String apply(Node from) { return from.getName(); } }); nodeDeleter.execute(nodeNames); clientDeleter.execute(nodeNames); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/strategy/internal/CreateNodeAndPopulateAutomaticAttributesImpl.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.strategy.internal; import static com.google.common.base.Preconditions.checkNotNull; import java.util.Map; import jakarta.annotation.Resource; import jakarta.inject.Inject; import jakarta.inject.Named; import jakarta.inject.Singleton; import org.jclouds.chef.ChefApi; import org.jclouds.chef.config.ChefProperties; import org.jclouds.chef.domain.Node; import org.jclouds.chef.strategy.CreateNodeAndPopulateAutomaticAttributes; import org.jclouds.domain.JsonBall; import org.jclouds.logging.Logger; import org.jclouds.ohai.Automatic; import com.google.common.base.Supplier; /** * * Updates node with new automatic attributes. */ @Singleton public class CreateNodeAndPopulateAutomaticAttributesImpl implements CreateNodeAndPopulateAutomaticAttributes { @Resource @Named(ChefProperties.CHEF_LOGGER) protected Logger logger = Logger.NULL; private final ChefApi chef; private final Supplier> automaticSupplier; @Inject public CreateNodeAndPopulateAutomaticAttributesImpl(ChefApi chef, @Automatic Supplier> automaticSupplier) { this.chef = checkNotNull(chef, "chef"); this.automaticSupplier = checkNotNull(automaticSupplier, "automaticSupplier"); } @Override public Node execute(Node node) { logger.trace("creating node %s", node.getName()); Node withAutomatic = Node.builder() // .name(node.getName()) // .normalAttributes(node.getNormalAttributes()) // .overrideAttributes(node.getOverrideAttributes()) // .defaultAttributes(node.getDefaultAttributes()) // .automaticAttributes(node.getAutomaticAttributes()) // .automaticAttributes(automaticSupplier.get()) // .runList(node.getRunList()) // .environment(node.getEnvironment()) // .build(); chef.createNode(withAutomatic); logger.debug("created node %s", withAutomatic.getName()); return node; } @Override public Node execute(String nodeName, Iterable runList) { return execute(Node.builder().name(nodeName).runList(runList).environment("_default").build()); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/strategy/internal/DeleteAllClientsInListImpl.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.strategy.internal; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.collect.Iterables.transform; import static com.google.common.util.concurrent.Futures.allAsList; import static com.google.common.util.concurrent.Futures.getUnchecked; import java.util.List; import java.util.concurrent.Callable; import jakarta.annotation.Resource; import jakarta.inject.Named; import jakarta.inject.Singleton; import org.jclouds.Constants; import org.jclouds.chef.ChefApi; import org.jclouds.chef.config.ChefProperties; import org.jclouds.chef.domain.Client; import org.jclouds.chef.strategy.DeleteAllClientsInList; import org.jclouds.logging.Logger; import com.google.common.base.Function; import com.google.common.base.Joiner; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.inject.Inject; /** * Concurrently delete all given clients. */ @Singleton public class DeleteAllClientsInListImpl implements DeleteAllClientsInList { protected final ChefApi api; protected final ListeningExecutorService userExecutor; @Resource @Named(ChefProperties.CHEF_LOGGER) protected Logger logger = Logger.NULL; @Inject DeleteAllClientsInListImpl(@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, ChefApi api) { this.userExecutor = checkNotNull(userExecutor, "userExecuor"); this.api = checkNotNull(api, "api"); } @Override public void execute(Iterable names) { execute(userExecutor, names); } @Override public void execute(final ListeningExecutorService executor, Iterable names) { ListenableFuture> futures = allAsList(transform(names, new Function>() { @Override public ListenableFuture apply(final String input) { return executor.submit(new Callable() { @Override public Client call() throws Exception { return api.deleteClient(input); } }); } })); logger.trace(String.format("deleting clients: %s", Joiner.on(',').join(names))); getUnchecked(futures); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/strategy/internal/DeleteAllNodesInListImpl.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.strategy.internal; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.collect.Iterables.transform; import static com.google.common.util.concurrent.Futures.allAsList; import static com.google.common.util.concurrent.Futures.getUnchecked; import java.util.List; import java.util.concurrent.Callable; import jakarta.annotation.Resource; import jakarta.inject.Named; import jakarta.inject.Singleton; import org.jclouds.Constants; import org.jclouds.chef.ChefApi; import org.jclouds.chef.config.ChefProperties; import org.jclouds.chef.domain.Node; import org.jclouds.chef.strategy.DeleteAllNodesInList; import org.jclouds.logging.Logger; import com.google.common.base.Function; import com.google.common.base.Joiner; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.inject.Inject; @Singleton public class DeleteAllNodesInListImpl implements DeleteAllNodesInList { protected final ChefApi api; protected final ListeningExecutorService userExecutor; @Resource @Named(ChefProperties.CHEF_LOGGER) protected Logger logger = Logger.NULL; @Inject DeleteAllNodesInListImpl(@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, ChefApi api) { this.userExecutor = checkNotNull(userExecutor, "userExecuor"); this.api = checkNotNull(api, "api"); } @Override public void execute(Iterable names) { execute(userExecutor, names); } @Override public void execute(final ListeningExecutorService executor, Iterable names) { ListenableFuture> futures = allAsList(transform(names, new Function>() { @Override public ListenableFuture apply(final String input) { return executor.submit(new Callable() { @Override public Node call() throws Exception { return api.deleteNode(input); } }); } })); logger.trace(String.format("deleting nodes: %s", Joiner.on(',').join(names))); getUnchecked(futures); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/strategy/internal/ListClientsImpl.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.strategy.internal; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.collect.Iterables.transform; import static com.google.common.util.concurrent.Futures.allAsList; import static com.google.common.util.concurrent.Futures.getUnchecked; import java.util.List; import java.util.concurrent.Callable; import jakarta.annotation.Resource; import jakarta.inject.Named; import jakarta.inject.Singleton; import com.google.common.base.Function; import com.google.common.base.Joiner; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.MoreExecutors; import com.google.inject.Inject; import org.jclouds.chef.ChefApi; import org.jclouds.chef.config.ChefProperties; import org.jclouds.chef.domain.Client; import org.jclouds.chef.strategy.ListClients; import org.jclouds.logging.Logger; import java.util.concurrent.ExecutorService; @Singleton public class ListClientsImpl implements ListClients { protected final ChefApi api; @Resource @Named(ChefProperties.CHEF_LOGGER) protected Logger logger = Logger.NULL; @Inject ListClientsImpl(ChefApi api) { this.api = checkNotNull(api, "api"); } @Override public Iterable execute() { Iterable toGet = api.listClients(); Iterable clients = transform(toGet, new Function() { @Override public Client apply(final String input) { return api.getClient(input); } } ); logger.trace(String.format("getting clients: %s", Joiner.on(',').join(toGet))); return clients; } @Override public Iterable execute(ExecutorService executorService) { return this.execute(MoreExecutors.listeningDecorator(executorService)); } private Iterable execute(ListeningExecutorService listeningExecutor) { return executeConcurrently(listeningExecutor, api.listClients()); } private Iterable executeConcurrently(final ListeningExecutorService executor, Iterable toGet) { ListenableFuture> futures = allAsList(transform(toGet, new Function>() { @Override public ListenableFuture apply(final String input) { return executor.submit(new Callable() { @Override public Client call() throws Exception { return api.getClient(input); } }); } } )); logger.trace(String.format("getting clients: %s", Joiner.on(',').join(toGet))); return getUnchecked(futures); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/strategy/internal/ListCookbookVersionsImpl.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.strategy.internal; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.MoreExecutors; import com.google.inject.Inject; import org.jclouds.chef.ChefApi; import org.jclouds.chef.config.ChefProperties; import org.jclouds.chef.domain.CookbookVersion; import org.jclouds.chef.strategy.ListCookbookVersions; import org.jclouds.logging.Logger; import jakarta.annotation.Resource; import jakarta.inject.Named; import jakarta.inject.Singleton; import java.util.concurrent.ExecutorService; @Singleton public class ListCookbookVersionsImpl extends BaseListCookbookVersionsImpl implements ListCookbookVersions { @Resource @Named(ChefProperties.CHEF_LOGGER) protected Logger logger = Logger.NULL; @Inject ListCookbookVersionsImpl(ChefApi api) { super(api); } @Override public Iterable execute() { return super.execute(api.listCookbooks()); } @Override public Iterable execute(ExecutorService executor) { return this.executeConcurrently(MoreExecutors.listeningDecorator(executor)); } private Iterable executeConcurrently(ListeningExecutorService executor) { return super.executeConcurrently(executor, api.listCookbooks()); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/strategy/internal/ListCookbookVersionsInEnvironmentImpl.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.strategy.internal; import static com.google.common.collect.Iterables.transform; import jakarta.annotation.Resource; import jakarta.inject.Named; import jakarta.inject.Singleton; import com.google.common.base.Function; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.MoreExecutors; import com.google.inject.Inject; import org.jclouds.chef.ChefApi; import org.jclouds.chef.config.ChefProperties; import org.jclouds.chef.domain.CookbookDefinition; import org.jclouds.chef.domain.CookbookVersion; import org.jclouds.chef.strategy.ListCookbookVersionsInEnvironment; import org.jclouds.logging.Logger; import java.util.concurrent.ExecutorService; @Singleton public class ListCookbookVersionsInEnvironmentImpl extends BaseListCookbookVersionsImpl implements ListCookbookVersionsInEnvironment { @Resource @Named(ChefProperties.CHEF_LOGGER) protected Logger logger = Logger.NULL; @Inject ListCookbookVersionsInEnvironmentImpl(ChefApi api) { super(api); } @Override public Iterable execute(String environmentName) { return super.execute(transform(api.listCookbooksInEnvironment(environmentName), new Function() { @Override public String apply(CookbookDefinition cookbookDefinition) { return cookbookDefinition.getName(); } } )); } @Override public Iterable execute(String environmentName, String numVersions) { return super.execute(transform(api.listCookbooksInEnvironment(environmentName, numVersions), new Function() { @Override public String apply(CookbookDefinition cookbookDefinition) { return cookbookDefinition.getName(); } } )); } @Override public Iterable execute(ExecutorService executor, String environmentName) { return this.executeConcurrently(MoreExecutors.listeningDecorator(executor), environmentName); } @Override public Iterable execute(ExecutorService executor, String environmentName, String numVersions) { return this.executeConcurrently(MoreExecutors.listeningDecorator(executor), environmentName, numVersions); } private Iterable executeConcurrently(ListeningExecutorService executor, String environmentName) { return super.execute( transform(api.listCookbooksInEnvironment(environmentName), new Function() { @Override public String apply(CookbookDefinition cookbookDefinition) { return cookbookDefinition.getName(); } }) ); } private Iterable executeConcurrently(ListeningExecutorService executor, String environmentName, String numVersions) { return super.execute(transform(api.listCookbooksInEnvironment(environmentName, numVersions), new Function() { @Override public String apply(CookbookDefinition cookbookDefinition) { return cookbookDefinition.getName(); } } )); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/strategy/internal/ListEnvironmentsImpl.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.strategy.internal; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.collect.Iterables.transform; import static com.google.common.util.concurrent.Futures.allAsList; import static com.google.common.util.concurrent.Futures.getUnchecked; import java.util.List; import java.util.concurrent.Callable; import jakarta.annotation.Resource; import jakarta.inject.Named; import jakarta.inject.Singleton; import org.jclouds.Constants; import org.jclouds.chef.ChefApi; import org.jclouds.chef.config.ChefProperties; import org.jclouds.chef.domain.Environment; import org.jclouds.chef.strategy.ListEnvironments; import org.jclouds.logging.Logger; import com.google.common.base.Function; import com.google.common.base.Joiner; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.inject.Inject; import com.google.common.util.concurrent.MoreExecutors; import java.util.concurrent.ExecutorService; @Singleton public class ListEnvironmentsImpl implements ListEnvironments { protected final ChefApi api; protected final ListeningExecutorService userExecutor; @Resource @Named(ChefProperties.CHEF_LOGGER) protected Logger logger = Logger.NULL; @Inject ListEnvironmentsImpl(@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, ChefApi api) { this.userExecutor = checkNotNull(userExecutor, "userExecuor"); this.api = checkNotNull(api, "api"); } @Override public Iterable execute() { return execute(userExecutor); } @Override public Iterable execute(ExecutorService executor) { return this.execute(MoreExecutors.listeningDecorator(executor)); } private Iterable execute(ListeningExecutorService executor) { return execute(executor, api.listEnvironments()); } private Iterable execute(final ListeningExecutorService executor, Iterable toGet) { ListenableFuture> futures = allAsList(transform(toGet, new Function>() { @Override public ListenableFuture apply(final String input) { return executor.submit(new Callable() { @Override public Environment call() throws Exception { return api.getEnvironment(input); } }); } })); logger.trace(String.format("deleting environments: %s", Joiner.on(',').join(toGet))); return getUnchecked(futures); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/strategy/internal/ListNodesImpl.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.strategy.internal; import jakarta.annotation.Resource; import jakarta.inject.Named; import jakarta.inject.Singleton; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.MoreExecutors; import com.google.inject.Inject; import org.jclouds.chef.ChefApi; import org.jclouds.chef.config.ChefProperties; import org.jclouds.chef.domain.Node; import org.jclouds.chef.strategy.ListNodes; import org.jclouds.logging.Logger; import java.util.concurrent.ExecutorService; @Singleton public class ListNodesImpl extends BaseListNodesImpl implements ListNodes { @Resource @Named(ChefProperties.CHEF_LOGGER) protected Logger logger = Logger.NULL; @Inject ListNodesImpl(ChefApi api) { super(api); } @Override public Iterable execute() { return super.execute(api.listNodes()); } @Override public Iterable execute(ExecutorService executor) { return this.executeConcurrently(MoreExecutors.listeningDecorator(executor)); } private Iterable executeConcurrently(ListeningExecutorService executor) { return super.executeConcurrently(executor, api.listNodes()); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/strategy/internal/ListNodesInEnvironmentImpl.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.strategy.internal; import jakarta.annotation.Resource; import jakarta.inject.Named; import jakarta.inject.Singleton; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.MoreExecutors; import com.google.inject.Inject; import org.jclouds.chef.ChefApi; import org.jclouds.chef.config.ChefProperties; import org.jclouds.chef.domain.Node; import org.jclouds.chef.strategy.ListNodesInEnvironment; import org.jclouds.logging.Logger; import java.util.concurrent.ExecutorService; @Singleton public class ListNodesInEnvironmentImpl extends BaseListNodesImpl implements ListNodesInEnvironment { @Resource @Named(ChefProperties.CHEF_LOGGER) protected Logger logger = Logger.NULL; @Inject ListNodesInEnvironmentImpl(ChefApi api) { super(api); } @Override public Iterable execute(String environmentName) { return super.execute(api.listNodesInEnvironment(environmentName)); } @Override public Iterable execute(ExecutorService executor, String environmentName) { return this.executeConcurrently(MoreExecutors.listeningDecorator(executor), environmentName); } private Iterable executeConcurrently(ListeningExecutorService executor, String environmentName) { return super.executeConcurrently(executor, api.listNodesInEnvironment(environmentName)); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/strategy/internal/UpdateAutomaticAttributesOnNodeImpl.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.strategy.internal; import static com.google.common.base.Preconditions.checkNotNull; import java.util.Map; import jakarta.annotation.Resource; import jakarta.inject.Inject; import jakarta.inject.Named; import jakarta.inject.Singleton; import org.jclouds.chef.ChefApi; import org.jclouds.chef.config.ChefProperties; import org.jclouds.chef.domain.Node; import org.jclouds.chef.strategy.UpdateAutomaticAttributesOnNode; import org.jclouds.domain.JsonBall; import org.jclouds.logging.Logger; import org.jclouds.ohai.Automatic; import com.google.common.base.Supplier; /** * * Updates node with new automatic attributes. */ @Singleton public class UpdateAutomaticAttributesOnNodeImpl implements UpdateAutomaticAttributesOnNode { @Resource @Named(ChefProperties.CHEF_LOGGER) protected Logger logger = Logger.NULL; private final ChefApi chef; private final Supplier> automaticSupplier; @Inject public UpdateAutomaticAttributesOnNodeImpl(ChefApi chef, @Automatic Supplier> automaticSupplier) { this.chef = checkNotNull(chef, "chef"); this.automaticSupplier = checkNotNull(automaticSupplier, "automaticSupplier"); } @Override public void execute(String nodeName) { logger.trace("updating node %s", nodeName); Node node = chef.getNode(nodeName); Node updated = Node.builder() // .name(node.getName()) // .normalAttributes(node.getNormalAttributes()) // .overrideAttributes(node.getOverrideAttributes()) // .defaultAttributes(node.getDefaultAttributes()) // .automaticAttributes(automaticSupplier.get()) // .runList(node.getRunList()) // .environment(node.getEnvironment()) // .build(); chef.updateNode(updated); logger.debug("updated node %s", nodeName); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/suppliers/ChefVersionSupplier.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.suppliers; import static com.google.common.base.MoreObjects.firstNonNull; import static com.google.common.base.Preconditions.checkNotNull; import java.util.regex.Matcher; import java.util.regex.Pattern; import jakarta.annotation.Resource; import jakarta.inject.Inject; import jakarta.inject.Named; import jakarta.inject.Singleton; import org.jclouds.chef.config.ChefProperties; import org.jclouds.logging.Logger; import org.jclouds.rest.annotations.ApiVersion; import com.google.common.base.Supplier; /** * Properly supply the version of the Chef Server. */ @Singleton public class ChefVersionSupplier implements Supplier { /** The default version to assume in case we can not parse it. */ public static final Integer FALLBACK_VERSION = 10; @Resource @Named(ChefProperties.CHEF_LOGGER) private Logger logger = Logger.NULL; /** The configured version of the Chef Server API. */ private final String apiVersion; @Inject ChefVersionSupplier(@ApiVersion String apiVersion) { this.apiVersion = checkNotNull(apiVersion, "apiVersion must not be null"); } @Override public Integer get() { // Old versions of Chef have versions like 0.9.x, 0.10.x, but newer // versions are in the format 10.x.y, 11.x.y Pattern versionPattern = Pattern.compile("(?:0\\.(\\d+)|(\\d+)\\.\\d+)(?:\\.\\d)*"); Matcher m = versionPattern.matcher(apiVersion); if (!m.matches()) { logger.warn("Configured version does not match the standard version pattern. Assuming version %s", FALLBACK_VERSION); return FALLBACK_VERSION; } return Integer.valueOf(firstNonNull(m.group(1), m.group(2))); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/util/ChefUtils.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.util; import static com.google.common.base.Preconditions.checkNotNull; import java.util.Date; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.jclouds.domain.JsonBall; import org.jclouds.ohai.Automatic; import com.google.common.base.Predicate; import com.google.common.base.Supplier; import com.google.common.collect.Iterables; import com.google.inject.Binder; import com.google.inject.TypeLiteral; import com.google.inject.multibindings.MapBinder; public class ChefUtils { public static Date fromOhaiTime(JsonBall ohaiDate) { return new Date(Long.parseLong(checkNotNull(ohaiDate, "ohaiDate").toString().replaceAll("\\.[0-9]*$", ""))); } public static JsonBall toOhaiTime(long millis) { return new JsonBall(millis + ""); } public static MapBinder> ohaiAutomaticAttributeBinder(Binder binder) { MapBinder> mapbinder = MapBinder.newMapBinder(binder, new TypeLiteral() { }, new TypeLiteral>() { }, Automatic.class); return mapbinder; } /** * * @return NoSuchElementException if no element in the runList is a role. */ public static String findRoleInRunList(List runList) { final Pattern pattern = Pattern.compile("^role\\[(.*)\\]$"); String roleToParse = Iterables.find(runList, new Predicate() { @Override public boolean apply(String input) { return pattern.matcher(input).matches(); } }); Matcher matcher = pattern.matcher(roleToParse); matcher.find(); return matcher.group(1); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/util/CollectionUtils.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.util; import java.util.List; import java.util.Map; import java.util.Set; import org.jclouds.javax.annotation.Nullable; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; /** * Utility methods to work with collections. */ public class CollectionUtils { /** * Creates an immutable list with the elements of the given list. If the * input list is null, it returns an empty list. * * @param input * The list used to build the immutable one. * @return An immutable list with the elements of the given list. */ public static ImmutableList copyOfOrEmpty(@Nullable List input) { return input == null ? ImmutableList. of() : ImmutableList.copyOf(input); } /** * Creates an immutable set with the elements of the given set. If the input * set is null, it returns an empty set. * * @param input * The set used to build the immutable one. * @return An immutable set with the elements of the given set. */ public static ImmutableSet copyOfOrEmpty(@Nullable Set input) { return input == null ? ImmutableSet. of() : ImmutableSet.copyOf(input); } /** * Creates an immutable map with the elements of the given map. If the input * map is null, it returns an empty map. * * @param input * The map used to build the immutable one. * @return An immutable map with the elements of the given map. */ public static ImmutableMap copyOfOrEmpty(@Nullable Map input) { return input == null ? ImmutableMap. of() : ImmutableMap.copyOf(input); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/chef/util/RunListBuilder.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.util; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.collect.Iterables.addAll; import static com.google.common.collect.Lists.newArrayList; import static com.google.common.collect.Lists.transform; import java.util.Arrays; import java.util.List; import com.google.common.base.Function; import com.google.common.collect.ImmutableList; /** * builds a run list in the correct syntax for chef. */ public class RunListBuilder { private List list = newArrayList(); /** * Add the following recipe to the run list */ public RunListBuilder addRecipe(String recipe) { return addRecipes(checkNotNull(recipe, "recipe")); } /** * Add the following recipes to the run list */ public RunListBuilder addRecipes(String... recipes) { addAll(list, transform(Arrays.asList(checkNotNull(recipes, "recipes")), new Function() { @Override public String apply(String from) { return "recipe[" + from + "]"; } })); return this; } /** * Add the following role to the run list */ public RunListBuilder addRole(String role) { return addRoles(checkNotNull(role, "role")); } /** * Add the following roles to the run list */ public RunListBuilder addRoles(String... roles) { addAll(list, transform(Arrays.asList(checkNotNull(roles, "roles")), new Function() { @Override public String apply(String from) { return "role[" + from + "]"; } })); return this; } public List build() { return ImmutableList.copyOf(list); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/ohai/Automatic.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.ohai; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Retention; import java.lang.annotation.Target; import jakarta.inject.Qualifier; @Retention(RUNTIME) @Target({ TYPE, METHOD, PARAMETER }) @Qualifier public @interface Automatic { } ================================================ FILE: apis/chef/src/main/java/org/jclouds/ohai/AutomaticSupplier.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.ohai; import static com.google.common.base.Preconditions.checkNotNull; import java.util.Map; import jakarta.inject.Inject; import jakarta.inject.Singleton; import org.jclouds.domain.JsonBall; import org.jclouds.ohai.functions.NestSlashKeys; import com.google.common.base.Supplier; import com.google.common.collect.Multimap; @Singleton public class AutomaticSupplier implements Supplier> { private final Multimap> autoAttrs; private final NestSlashKeys nester; @Inject AutomaticSupplier(@Automatic Multimap> autoAttrs, NestSlashKeys nester) { this.autoAttrs = checkNotNull(autoAttrs, "autoAttrs"); this.nester = checkNotNull(nester, "nester"); } @Override public Map get() { return nester.apply(autoAttrs); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/ohai/config/ConfiguresOhai.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.ohai.config; import java.lang.annotation.Retention; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.RUNTIME; @Retention(RUNTIME) @Target(TYPE) public @interface ConfiguresOhai { } ================================================ FILE: apis/chef/src/main/java/org/jclouds/ohai/config/JMXOhaiModule.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.ohai.config; import java.lang.management.ManagementFactory; import java.lang.management.RuntimeMXBean; import jakarta.inject.Singleton; import org.jclouds.domain.JsonBall; import org.jclouds.ohai.suppliers.UptimeSecondsSupplier; import com.google.common.base.Supplier; import com.google.inject.Provides; import com.google.inject.multibindings.MapBinder; /** * Wires the components needed to parse ohai data from a JVM */ @ConfiguresOhai public class JMXOhaiModule extends OhaiModule { @Provides @Singleton protected final RuntimeMXBean guiceProvideRuntimeMXBean() { return provideRuntimeMXBean(); } protected RuntimeMXBean provideRuntimeMXBean() { return ManagementFactory.getRuntimeMXBean(); } @Override public MapBinder> bindOhai() { MapBinder> mapBinder = super.bindOhai(); mapBinder.addBinding("uptime_seconds").to(UptimeSecondsSupplier.class); return mapBinder; } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/ohai/config/OhaiModule.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.ohai.config; import static org.jclouds.chef.util.ChefUtils.ohaiAutomaticAttributeBinder; import static org.jclouds.chef.util.ChefUtils.toOhaiTime; import java.util.Map; import java.util.Properties; import java.util.Set; import jakarta.inject.Inject; import jakarta.inject.Named; import jakarta.inject.Provider; import jakarta.inject.Singleton; import org.jclouds.date.TimeStamp; import org.jclouds.domain.JsonBall; import org.jclouds.json.Json; import org.jclouds.ohai.Automatic; import org.jclouds.ohai.AutomaticSupplier; import org.jclouds.ohai.functions.ByteArrayToMacAddress; import org.jclouds.ohai.functions.MapSetToMultimap; import com.google.common.base.Function; import com.google.common.base.Supplier; import com.google.common.collect.Multimap; import com.google.inject.AbstractModule; import com.google.inject.Provides; import com.google.inject.TypeLiteral; import com.google.inject.multibindings.MapBinder; /** * Wires the components needed to parse ohai data */ @ConfiguresOhai public class OhaiModule extends AbstractModule { @Override protected void configure() { bind(new TypeLiteral>() { }).to(new TypeLiteral() { }); bindOhai(); } @Provides @Automatic protected final Supplier> guiceProvideAutomatic(AutomaticSupplier in) { return provideAutomatic(in); } protected Supplier> provideAutomatic(AutomaticSupplier in) { return in; } @Provides @Automatic final Multimap> provideAutomatic(MapSetToMultimap> converter, @Automatic Map>> input) { return converter.apply(input); } @Named("systemProperties") @Provides protected final Properties provideSystemProperties() { return systemProperties(); } protected Properties systemProperties() { return System.getProperties(); } public MapBinder> bindOhai() { MapBinder> mapbinder = ohaiAutomaticAttributeBinder(binder()).permitDuplicates(); mapbinder.addBinding("ohai_time").to(OhaiTimeProvider.class); mapbinder.addBinding("jvm/system").to(SystemPropertiesProvider.class); mapbinder.addBinding("platform").to(PlatformProvider.class); mapbinder.addBinding("platform_version").to(PlatformVersionProvider.class); mapbinder.addBinding("current_user").to(CurrentUserProvider.class); return mapbinder; } @Singleton public static class OhaiTimeProvider implements Supplier { private final Provider timeProvider; @Inject OhaiTimeProvider(@TimeStamp Provider timeProvider) { this.timeProvider = timeProvider; } @Override public JsonBall get() { return toOhaiTime(timeProvider.get()); } } @Provides @TimeStamp protected final Long provideMillis() { return millis(); } protected Long millis() { return System.currentTimeMillis(); } @Singleton public static class SystemPropertiesProvider implements Supplier { private final Json json; private final Properties systemProperties; @Inject SystemPropertiesProvider(Json json, @Named("systemProperties") Properties systemProperties) { this.json = json; this.systemProperties = systemProperties; } @Override public JsonBall get() { return new JsonBall(json.toJson(systemProperties)); } } @Singleton public static class PlatformProvider extends SystemPropertyProvider { @Inject PlatformProvider(@Named("systemProperties") Properties systemProperties) { super("os.name", systemProperties); } @Override public JsonBall get() { JsonBall returnValue = super.get(); return returnValue != null ? new JsonBall(returnValue.toString().replaceAll("[ -]", "").toLowerCase()) : null; } } @Singleton public static class PlatformVersionProvider extends SystemPropertyProvider { @Inject PlatformVersionProvider(@Named("systemProperties") Properties systemProperties) { super("os.version", systemProperties); } } @Singleton public static class CurrentUserProvider extends SystemPropertyProvider { @Inject CurrentUserProvider(@Named("systemProperties") Properties systemProperties) { super("user.name", systemProperties); } } public static class SystemPropertyProvider implements Supplier { private final Properties systemProperties; private final String property; @Inject SystemPropertyProvider(String property, @Named("systemProperties") Properties systemProperties) { this.property = property; this.systemProperties = systemProperties; } @Override public JsonBall get() { return systemProperties.containsKey(property) ? new JsonBall(systemProperties.getProperty(property)) : null; } } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/ohai/functions/ByteArrayToMacAddress.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.ohai.functions; import static com.google.common.collect.Iterables.transform; import static com.google.common.collect.Lists.partition; import static com.google.common.io.BaseEncoding.base16; import static com.google.common.primitives.Bytes.asList; import static com.google.common.primitives.Bytes.toArray; import java.util.List; import jakarta.inject.Singleton; import com.google.common.base.Function; import com.google.common.base.Joiner; /** * * Creates a string in the form: {@code 00:26:bb:09:e6:c4 } */ @Singleton public class ByteArrayToMacAddress implements Function { @Override public String apply(byte[] from) { return Joiner.on(':').join(transform(partition(asList(from), 1), new Function, String>() { @Override public String apply(List from) { return base16().lowerCase().encode(toArray(from)); } })); } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/ohai/functions/MapSetToMultimap.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.ohai.functions; import java.util.Map; import java.util.Set; import java.util.Map.Entry; import jakarta.inject.Singleton; import com.google.common.base.Function; import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.Multimap; @Singleton public class MapSetToMultimap implements Function>, Multimap> { @Override public Multimap apply(Map> from) { Multimap returnV = LinkedHashMultimap.create(); for (Entry> entry : from.entrySet()) { for (V value : entry.getValue()) returnV.put(entry.getKey(), value); } return returnV; } } ================================================ FILE: apis/chef/src/main/java/org/jclouds/ohai/functions/NestSlashKeys.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.ohai.functions; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import java.lang.reflect.Type; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import jakarta.inject.Inject; import jakarta.inject.Singleton; import org.jclouds.domain.JsonBall; import org.jclouds.json.Json; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.base.Splitter; import com.google.common.base.Supplier; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Multimap; import com.google.common.collect.Sets; import com.google.inject.TypeLiteral; @Singleton public class NestSlashKeys implements Function>, Map> { private final Json json; @Inject NestSlashKeys(Json json) { this.json = checkNotNull(json, "json"); } @Override public Map apply(Multimap> from) { Map autoAttrs = mergeSameKeys(from); Map modifiableFlatMap = Maps.newLinkedHashMap(Maps.filterKeys(autoAttrs, new Predicate() { @Override public boolean apply(String input) { return input.indexOf('/') == -1; } })); Map withSlashesMap = Maps.difference(autoAttrs, modifiableFlatMap).entriesOnlyOnLeft(); for (Entry entry : withSlashesMap.entrySet()) { List keyParts = Lists.newArrayList(Splitter.on('/').split(entry.getKey())); JsonBall toInsert = entry.getValue(); try { putUnderContext(keyParts, toInsert, modifiableFlatMap); } catch (IllegalArgumentException e) { throw new IllegalArgumentException("error inserting value in entry: " + entry.getKey(), e); } } return modifiableFlatMap; } private Map mergeSameKeys(Multimap> from) { Map merged = Maps.newLinkedHashMap(); for (Entry> entry : from.entries()) { if (merged.containsKey(entry.getKey())) { mergeAsPeer(entry.getKey(), entry.getValue().get(), merged); } else { merged.put(entry.getKey(), entry.getValue().get()); } } return merged; } @VisibleForTesting void mergeAsPeer(String key, JsonBall value, Map insertionContext) { Map immutableValueContext = json.fromJson(insertionContext.get(key).toString(), mapLiteral); Map valueContext = Maps.newLinkedHashMap(immutableValueContext); Map toPut = json.> fromJson(value.toString(), mapLiteral); Set uniques = Sets.difference(toPut.keySet(), valueContext.keySet()); for (String k : uniques) { valueContext.put(k, toPut.get(k)); } Set conflicts = Sets.difference(toPut.keySet(), uniques); for (String k : conflicts) { JsonBall v = toPut.get(k); if (v.toString().matches("^\\{.*\\}$")) { mergeAsPeer(k, v, valueContext); } else { // replace valueContext.put(k, v); } } insertionContext.put(key, new JsonBall(json.toJson(valueContext, mapLiteral))); } /** * @param keyParts * @param toInsert * @param destination * @throws IllegalArgumentException *

* if destination.get(keyParts(0)) is not a map * *

* keyParts is zero length */ void putUnderContext(List keyParts, JsonBall toInsert, Map destination) { checkNotNull(keyParts, "keyParts"); checkArgument(keyParts.size() >= 1, "keyParts must contain at least one element"); checkNotNull(toInsert, "toInsert"); checkNotNull(destination, "destination"); String rootKey = keyParts.remove(0); String rootValue = destination.containsKey(rootKey) ? destination.get(rootKey).toString() : "{}"; checkArgument(rootValue.matches("^\\{.*\\}$"), "value must be a hash: %s", rootValue); Map immutableInsertionContext = json.fromJson(rootValue, mapLiteral); Map insertionContext = Maps.newLinkedHashMap(immutableInsertionContext); if (keyParts.size() == 1) { if (!insertionContext.containsKey(keyParts.get(0))) { insertionContext.put(keyParts.get(0), toInsert); } else { String key = keyParts.get(0); mergeAsPeer(key, toInsert, insertionContext); } } else { putUnderContext(keyParts, toInsert, insertionContext); } destination.put(rootKey, new JsonBall(json.toJson(insertionContext, mapLiteral))); } final Type mapLiteral = new TypeLiteral>() { }.getType(); final Type listLiteral = new TypeLiteral>() { }.getType(); } ================================================ FILE: apis/chef/src/main/java/org/jclouds/ohai/suppliers/UptimeSecondsSupplier.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.ohai.suppliers; import java.lang.management.RuntimeMXBean; import jakarta.inject.Inject; import jakarta.inject.Singleton; import org.jclouds.domain.JsonBall; import com.google.common.base.Supplier; @Singleton public class UptimeSecondsSupplier implements Supplier { @Inject UptimeSecondsSupplier(RuntimeMXBean runtime) { this.runtime = runtime; } private final RuntimeMXBean runtime; @Override public JsonBall get() { long uptimeInSeconds = runtime.getUptime() / 1000; return new JsonBall(uptimeInSeconds); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/BaseChefApiExpectTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef; import org.jclouds.chef.filters.SignedHeaderAuth; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; import org.jclouds.rest.internal.BaseRestApiExpectTest; import com.google.common.base.Functions; import com.google.common.collect.ImmutableMap; /** * Base class for Chef Api expect tests. */ public abstract class BaseChefApiExpectTest extends BaseRestApiExpectTest { public static final String PRIVATE_KEY = "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEAyb2ZJJqGm0KKR+8nfQJNsSd+F9tXNMV7CfOcW6jsqs8EZgiV\nR09hD1IYOj4YqM0qJONlgyg4xRWewdSG7QTPj1lJpVAida9sXy2+kzyagZA1Am0O\nZcbqb5hoeIDgcX+eDa79s0u0DomjcfO9EKhvHLBz+zM+3QqPRkPV8nYTbfs+HjVz\nzOU6D1B0XR3+IPZZl2AnWs2d0qhnStHcDUvnRVQ0P482YwN9VgceOZtpPz0DCKEJ\n5Tx5STub8k0/zt/VAMHQafLSuQMLd2s4ZLuOZptN//uAsTmxireqd37z+8ZTdBbJ\n8LEpJ+iCXuSfm5aUh7iw6oxvToY2AL53+jK2UQIDAQABAoIBAQDA88B3i/xWn0vX\nBVxFamCYoecuNjGwXXkSyZew616A+EOCu47bh4aTurdFbYL0YFaAtaWvzlaN2eHg\nDb+HDuTefE29+WkcGk6SshPmiz5T0XOCAICWw6wSVDkHmGwS4jZvbAFm7W8nwGk9\nYhxgxFiRngswJZFopOLoF5WXs2td8guIYNslMpo7tu50iFnBHwKO2ZsPAk8t9nnS\nxlDavKruymEmqHCr3+dtio5eaenJcp3fjoXBQOKUk3ipII29XRB8NqeCVV/7Kxwq\nckqOBEbRwBclckyIbD+RiAgKvOelORjEiE9R42vuqvxRA6k9kd9o7utlX0AUtpEn\n3gZc6LepAoGBAP9ael5Y75+sK2JJUNOOhO8ae45cdsilp2yI0X+UBaSuQs2+dyPp\nkpEHAxd4pmmSvn/8c9TlEZhr+qYbABXVPlDncxpIuw2Ajbk7s/S4XaSKsRqpXL57\nzj/QOqLkRk8+OVV9q6lMeQNqLtEj1u6JPviX70Ro+FQtRttNOYbfdP/fAoGBAMpA\nXjR5woV5sUb+REg9vEuYo8RSyOarxqKFCIXVUNsLOx+22+AK4+CQpbueWN7jotrl\nYD6uT6svWi3AAC7kiY0UI/fjVPRCUi8tVoQUE0TaU5VLITaYOB+W/bBaDE4M9560\n1NuDWO90baA5dfU44iuzva02rGJXK9+nS3o8nk/PAoGBALOL6djnDe4mwAaG6Jco\ncd4xr8jkyPzCRZuyBCSBbwphIUXLc7hDprPky064ncJD1UDmwIdkXd/fpMkg2QmA\n/CUk6LEFjMisqHojOaCL9gQZJPhLN5QUN2x1PJWGjs1vQh8Tkx0iUUCOa8bQPXNR\n+34OTsW6TUna4CSZAycLfhffAoGBAIggVsefBCvuQkF0NeUhmDCRZfhnd8y55RHR\n1HCvqKIlpv+rhcX/zmyBLuteopYyRJRsOiE2FW00i8+rIPRu4Z3Q5nybx7w3PzV9\noHN5R5baE9OyI4KpZWztpYYitZF67NcnAvVULHHOvVJQGnKYfLHJYmrJF7GA1ojM\nAuMdFbjFAoGAPxUhxwFy8gaqBahKUEZn4F81HFP5ihGhkT4QL6AFPO2e+JhIGjuR\n27+85hcFqQ+HHVtFsm81b/a+R7P4UuCRgc8eCjxQMoJ1Xl4n7VbjPbHMnIN0Ryvd\nO4ZpWDWYnCO021JTOUUOJ4J/y0416Bvkw0z59y7sNX7wDBBHHbK/XCc=\n-----END RSA PRIVATE KEY-----\n"; protected SignedHeaderAuth signedHeaderAuth; public BaseChefApiExpectTest() { provider = "chef"; credential = PRIVATE_KEY; signedHeaderAuth = createInjector(Functions.forMap(ImmutableMap. of()), createModule(), setupProperties()).getInstance(SignedHeaderAuth.class); } protected HttpRequest signed(HttpRequest input) { return signedHeaderAuth.filter(input); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/ChefApiDelegationTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import java.io.IOException; import org.jclouds.ContextBuilder; import org.testng.annotations.Test; @Test(groups = "unit", testName = "ChefApiDelegationTest") public class ChefApiDelegationTest { public void testOrganizationApiNotAvailableInOldVersions() throws IOException { ChefApi chef = ContextBuilder.newBuilder(new ChefApiMetadata()) .credentials("foo", "bar") .apiVersion("11.0.4") .buildApi(ChefApi.class); try { assertFalse(chef.organizationApi().isPresent()); } finally { chef.close(); } } public void testOrganizationApiPresentInRecentVersions() throws IOException { ChefApi chef = ContextBuilder.newBuilder(new ChefApiMetadata()) .credentials("foo", "bar") .apiVersion("12.0.4") .buildApi(ChefApi.class); try { assertTrue(chef.organizationApi().isPresent()); } finally { chef.close(); } } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/ChefApiExpectTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; import java.util.Set; import jakarta.ws.rs.core.MediaType; import org.jclouds.chef.config.ChefHttpApiModule; import org.jclouds.chef.domain.CookbookDefinition; import org.jclouds.chef.domain.Role; import org.jclouds.chef.domain.SearchResult; import org.jclouds.chef.options.SearchOptions; import org.jclouds.date.TimeStamp; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; import org.jclouds.rest.ConfiguresHttpApi; import org.testng.annotations.Test; import com.google.common.base.Supplier; import com.google.inject.Module; /** * Expect tests for the {@link ChefApi} class. */ @Test(groups = "unit", testName = "ChefApiExpectTest") public class ChefApiExpectTest extends BaseChefApiExpectTest { private HttpRequest.Builder getHttpRequestBuilder(String method, String endPoint) { return HttpRequest.builder() // .method(method) // .endpoint("http://localhost:4000" + endPoint) // .addHeader("X-Chef-Version", ChefApiMetadata.DEFAULT_API_VERSION) // .addHeader("Accept", MediaType.APPLICATION_JSON); } public void testListClientsReturnsValidSet() { ChefApi api = requestSendsResponse( signed(getHttpRequestBuilder("GET", "/clients").build()), HttpResponse.builder().statusCode(200) // .payload(payloadFromResourceWithContentType("/clients_list.json", MediaType.APPLICATION_JSON)) // .build()); Set nodes = api.listClients(); assertEquals(nodes.size(), 3); assertTrue(nodes.contains("adam"), String.format("Expected nodes to contain 'adam' but was: %s", nodes)); } public void testListClientsReturnsEmptySetOn404() { ChefApi api = requestSendsResponse( signed(getHttpRequestBuilder("GET", "/clients").build()), HttpResponse.builder().statusCode(404) .build()); Set clients = api.listClients(); assertTrue(clients.isEmpty(), String.format("Expected clients to be empty but was: %s", clients)); } public void testListNodesReturnsValidSet() { ChefApi api = requestSendsResponse( signed(getHttpRequestBuilder("GET", "/nodes").build()), HttpResponse.builder().statusCode(200) .payload(payloadFromResourceWithContentType("/nodes_list.json", MediaType.APPLICATION_JSON)) // .build()); Set nodes = api.listNodes(); assertEquals(nodes.size(), 3); assertTrue(nodes.contains("blah"), String.format("Expected nodes to contain 'blah' but was: %s", nodes)); } public void testListNodesReturnsEmptySetOn404() { ChefApi api = requestSendsResponse( signed(getHttpRequestBuilder("GET", "/nodes").build()), HttpResponse.builder().statusCode(404).build()); Set nodes = api.listNodes(); assertTrue(nodes.isEmpty(), String.format("Expected nodes to be empty but was: %s", nodes)); } public void testListRecipesInEnvironmentReturnsValidSet() { ChefApi api = requestSendsResponse( signed(getHttpRequestBuilder("GET", "/environments/dev/recipes").build()), HttpResponse.builder().statusCode(200) .payload(payloadFromResourceWithContentType("/environment_recipes.json", MediaType.APPLICATION_JSON)) // .build()); Set recipes = api.listRecipesInEnvironment("dev"); assertEquals(recipes.size(), 3); assertTrue(recipes.contains("apache2"), String.format("Expected recipes to contain 'apache2' but was: %s", recipes)); } public void testListRecipesInEnvironmentReturnsEmptySetOn404() { ChefApi api = requestSendsResponse( signed(getHttpRequestBuilder("GET", "/environments/dev/recipes").build()), HttpResponse.builder().statusCode(404).build()); Set recipes = api.listRecipesInEnvironment("dev"); assertTrue(recipes.isEmpty(), String.format("Expected recipes to be empty but was: %s", recipes)); } public void testListNodesInEnvironmentReturnsValidSet() { ChefApi api = requestSendsResponse( signed(getHttpRequestBuilder("GET", "/environments/dev/nodes").build()), HttpResponse.builder().statusCode(200) .payload(payloadFromResourceWithContentType("/nodes_list.json", MediaType.APPLICATION_JSON)) // .build()); Set nodes = api.listNodesInEnvironment("dev"); assertEquals(nodes.size(), 3); assertTrue(nodes.contains("blah"), String.format("Expected nodes to contain 'blah' but was: %s", nodes)); } public void testListNodesInEnvironmentReturnsEmptySetOn404() { ChefApi api = requestSendsResponse( signed(getHttpRequestBuilder("GET", "/environments/dev/nodes").build()), HttpResponse.builder().statusCode(404).build()); Set nodes = api.listNodesInEnvironment("dev"); assertTrue(nodes.isEmpty(), String.format("Expected nodes to be empty but was: %s", nodes)); } public void testListCookbooksReturnsValidSet() { ChefApi api = requestSendsResponse( signed(getHttpRequestBuilder("GET", "/cookbooks").build()), HttpResponse.builder().statusCode(200) .payload(payloadFromResourceWithContentType("/env_cookbooks.json", MediaType.APPLICATION_JSON)) // .build()); Set cookbooks = api.listCookbooks(); assertEquals(cookbooks.size(), 2); assertTrue(cookbooks.contains("apache2"), String.format("Expected cookbooks to contain 'apache2' but was: %s", cookbooks)); } public void testListCookbooksReturnsEmptySetOn404() { ChefApi api = requestSendsResponse( signed(getHttpRequestBuilder("GET", "/cookbooks").build()), HttpResponse.builder().statusCode(404).build()); Set cookbooks = api.listCookbooks(); assertTrue(cookbooks.isEmpty(), String.format("Expected cookbooks to be empty but was: %s", cookbooks)); } public void testListCookbooksInEnvironmentReturnsValidSet() { ChefApi api = requestSendsResponse( signed(getHttpRequestBuilder("GET", "/environments/dev/cookbooks").build()), HttpResponse.builder().statusCode(200) .payload(payloadFromResourceWithContentType("/env_cookbooks.json", MediaType.APPLICATION_JSON)) // .build()); Set cookbooks = api.listCookbooksInEnvironment("dev"); assertEquals(cookbooks.size(), 2); } public void testListCookbooksInEnvironmentReturnsEmptySetOn404() { ChefApi api = requestSendsResponse( signed(getHttpRequestBuilder("GET", "/environments/dev/cookbooks").build()), HttpResponse.builder().statusCode(404).build()); Set cookbooks = api.listCookbooksInEnvironment("dev"); assertTrue(cookbooks.isEmpty(), String.format("Expected cookbooks to be empty but was: %s", cookbooks)); } public void testListCookbooksInEnvironmentWithNumVersionReturnsEmptySetOn404() { ChefApi api = requestSendsResponse( signed(getHttpRequestBuilder("GET", "/environments/dev/cookbooks").addQueryParam("num_versions", "2").build()), HttpResponse.builder().statusCode(404).build()); Set cookbooks = api.listCookbooksInEnvironment("dev", "2"); assertTrue(cookbooks.isEmpty(), String.format("Expected cookbooks to be empty but was: %s", cookbooks)); } public void testSearchRolesReturnsValidResult() { ChefApi api = requestSendsResponse( signed(getHttpRequestBuilder("GET", "/search/role").build()), HttpResponse.builder().statusCode(200) .payload(payloadFromResourceWithContentType("/search_role.json", MediaType.APPLICATION_JSON)) // .build()); SearchResult result = api.searchRoles(); assertEquals(result.size(), 1); assertEquals(result.iterator().next().getName(), "webserver"); } public void testSearchRolesReturnsEmptyResult() { ChefApi api = requestSendsResponse( signed(getHttpRequestBuilder("GET", "/search/role").build()), HttpResponse.builder().statusCode(200) .payload(payloadFromResourceWithContentType("/search_role_empty.json", MediaType.APPLICATION_JSON)) // .build()); SearchResult result = api.searchRoles(); assertTrue(result.isEmpty(), String.format("Expected search result to be empty but was: %s", result)); } public void testSearchRolesWithOptionsReturnsValidResult() { ChefApi api = requestSendsResponse( signed(getHttpRequestBuilder("GET", "/search/role").addQueryParam("q", "name:webserver").build()), HttpResponse.builder().statusCode(200) .payload(payloadFromResourceWithContentType("/search_role.json", MediaType.APPLICATION_JSON)) // .build()); SearchOptions options = SearchOptions.Builder.query("name:webserver"); SearchResult result = api.searchRoles(options); assertEquals(result.size(), 1); assertEquals(result.iterator().next().getName(), "webserver"); } public void testSearchRolesWithOptionsReturnsEmptyResult() { ChefApi api = requestSendsResponse( signed(getHttpRequestBuilder("GET", "/search/role").addQueryParam("q", "name:dummy").build()), HttpResponse.builder().statusCode(200) .payload(payloadFromResourceWithContentType("/search_role_empty.json", MediaType.APPLICATION_JSON)) // .build()); SearchOptions options = SearchOptions.Builder.query("name:dummy"); SearchResult result = api.searchRoles(options); assertTrue(result.isEmpty(), String.format("Expected search result to be empty but was: %s", result)); } public void testListRolesReturnsValidSet() { ChefApi api = requestSendsResponse( signed(getHttpRequestBuilder("GET", "/roles").build()), HttpResponse.builder().statusCode(200) .payload(payloadFromResourceWithContentType("/roles_list.json", MediaType.APPLICATION_JSON)) // .build()); Set roles = api.listRoles(); assertEquals(roles.size(), 2); assertTrue(roles.contains("webserver"), String.format("Expected roles to contain 'websever' but was: %s", roles)); } public void testListRolesReturnsEmptySetOn404() { ChefApi api = requestSendsResponse( signed(getHttpRequestBuilder("GET", "/roles").build()), HttpResponse.builder().statusCode(404).build()); Set roles = api.listRoles(); assertTrue(roles.isEmpty(), String.format("Expected roles to be empty but was: %s", roles)); } public void testListDatabagsReturnsValidSet() { ChefApi api = requestSendsResponse( signed(getHttpRequestBuilder("GET", "/data").build()), HttpResponse.builder().statusCode(200) .payload(payloadFromResourceWithContentType("/data_list.json", MediaType.APPLICATION_JSON)) // .build()); Set databags = api.listDatabags(); assertEquals(databags.size(), 2); assertTrue(databags.contains("applications"), String.format("Expected databags to contain 'applications' but was: %s", databags)); } public void testListDatabagsReturnsEmptySetOn404() { ChefApi api = requestSendsResponse( signed(getHttpRequestBuilder("GET", "/data").build()), HttpResponse.builder().statusCode(404).build()); Set databags = api.listDatabags(); assertTrue(databags.isEmpty(), String.format("Expected databags to be empty but was: %s", databags)); } @Override protected Module createModule() { return new TestChefHttpApiModule(); } @ConfiguresHttpApi static class TestChefHttpApiModule extends ChefHttpApiModule { @Override protected String provideTimeStamp(@TimeStamp Supplier cache) { return "timestamp"; } } @Override protected ChefApiMetadata createApiMetadata() { return new ChefApiMetadata(); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/ChefApiLiveTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef; import static com.google.common.collect.Iterables.any; import static com.google.common.collect.Iterables.isEmpty; import static com.google.common.hash.Hashing.md5; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static org.jclouds.chef.domain.RoleTest.verifyRunListForEnvironment; import static org.jclouds.util.Closeables2.closeQuietly; import static org.jclouds.util.Predicates2.retry; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.Collections; import java.util.List; import java.util.Properties; import java.util.Set; import org.jclouds.chef.domain.ChecksumStatus; import org.jclouds.chef.domain.Client; import org.jclouds.chef.domain.CookbookDefinition; import org.jclouds.chef.domain.CookbookVersion; import org.jclouds.chef.domain.DatabagItem; import org.jclouds.chef.domain.Environment; import org.jclouds.chef.domain.Metadata; import org.jclouds.chef.domain.Node; import org.jclouds.chef.domain.Resource; import org.jclouds.chef.domain.Role; import org.jclouds.chef.domain.Sandbox; import org.jclouds.chef.domain.SearchResult; import org.jclouds.chef.domain.UploadSandbox; import org.jclouds.chef.internal.BaseChefLiveTest; import org.jclouds.chef.options.CreateClientOptions; import org.jclouds.chef.options.SearchOptions; import org.jclouds.crypto.Pems; import org.jclouds.io.ByteStreams2; import org.jclouds.io.Payloads; import org.jclouds.io.payloads.FilePayload; import org.jclouds.rest.ResourceNotFoundException; import org.testng.annotations.AfterClass; import org.testng.annotations.Test; import com.google.common.base.Predicate; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.hash.Hashing; import com.google.common.io.Files; import com.google.common.primitives.Bytes; /** * Tests behavior of {@code ChefApi} */ @Test(groups = { "live", "integration" }) public class ChefApiLiveTest extends BaseChefLiveTest { public static final String PREFIX = "jcloudstest-" + System.getProperty("user.name"); public static final String ADMIN_PREFIX = "jcloudstest-adm-" + System.getProperty("user.name"); public static final String ENV_NODE = PREFIX + "-env-node"; // It may take a bit until the search index is populated protected int maxWaitForIndexInMs = 60000; // The id of the data bag item used in search tests private String databagitemId; public void testCreateNewCookbook() throws Exception { // Define the file you want in the cookbook File file = new File(System.getProperty("user.dir"), "pom.xml"); FilePayload content = uploadAndGetFilePayload(file); // Create the metadata of the cookbook Metadata metadata = Metadata.builder() // .name(PREFIX) // .version("0.0.0") // .description("Jclouds test uploaded cookbook") // .maintainer("jclouds") // .maintainerEmail("someone@jclouds.org") // .license("Apache 2.0") // .build(); // Create a new cookbook CookbookVersion cookbook = CookbookVersion.builder(PREFIX, "0.0.0") // .metadata(metadata) // .rootFile(Resource.builder().fromPayload(content).build()) // .attribute(Resource.builder().fromPayload(content).name("default.rb").build()) .build(); // upload the cookbook to the remote server api.updateCookbook(PREFIX, "0.0.0", cookbook); } private FilePayload uploadAndGetFilePayload(File file) throws IOException { FilePayload content = Payloads.newFilePayload(file); content.getContentMetadata().setContentType("application/x-binary"); // Get an md5 so that you can see if the server already has it or not content.getContentMetadata().setContentMD5(Files.asByteSource(file).hash(Hashing.md5()).asBytes()); // Note that java collections cannot effectively do equals or hashcodes on // byte arrays, so let's convert to a list of bytes. List md5 = Bytes.asList(content.getContentMetadata().getContentMD5()); // Request an upload site for this file UploadSandbox site = api.createUploadSandboxForChecksums(ImmutableSet.of(md5)); assertTrue(site.getChecksums().containsKey(md5), md5 + " not in " + site.getChecksums()); try { // Upload the file contents, if still not uploaded ChecksumStatus status = site.getChecksums().get(md5); if (status.needsUpload()) { api.uploadContent(status.getUrl(), content); } Sandbox sandbox = api.commitSandbox(site.getSandboxId(), true); assertTrue(sandbox.isCompleted(), "Sandbox should be completed after uploading"); } catch (RuntimeException e) { api.commitSandbox(site.getSandboxId(), false); fail("Could not upload content"); } return content; } public void testListCookbooks() throws Exception { Set cookbookNames = api.listCookbooks(); assertFalse(cookbookNames.isEmpty(), "No cookbooks were found"); for (String cookbookName : cookbookNames) { Set versions = api.listVersionsOfCookbook(cookbookName); assertFalse(versions.isEmpty(), "There are no versions of the cookbook: " + cookbookName); for (String version : api.listVersionsOfCookbook(cookbookName)) { CookbookVersion cookbook = api.getCookbook(cookbookName, version); assertNotNull(cookbook, "Could not get cookbook: " + cookbookName); } } } @Test(dependsOnMethods = "testListCookbooks") public void testListCookbookVersionsWithChefService() throws Exception { Iterable cookbooks = chefService.listCookbookVersions(); assertFalse(isEmpty(cookbooks), "No cookbooks were found"); } @Test(dependsOnMethods = "testListCookbookVersionsWithChefService") public void testDownloadCookbooks() throws Exception { Iterable cookbooks = chefService.listCookbookVersions(); for (CookbookVersion cookbook : cookbooks) { for (Resource resource : ImmutableList. builder().addAll(cookbook.getDefinitions()) .addAll(cookbook.getFiles()).addAll(cookbook.getLibraries()).addAll(cookbook.getSuppliers()) .addAll(cookbook.getRecipes()).addAll(cookbook.getResources()).addAll(cookbook.getRootFiles()) .addAll(cookbook.getTemplates()).addAll(cookbook.getAttributes()).build()) { InputStream stream = api.getResourceContents(resource); assertNotNull(stream, "Resource contents are null for resource: " + resource.getName()); byte[] md5 = ByteStreams2.hashAndClose(stream, md5()).asBytes(); assertEquals(md5, resource.getChecksum()); } } } @Test(dependsOnMethods = "testCreateNewCookbook") public void testUpdateCookbook() throws Exception { CookbookVersion cookbook = api.getCookbook(PREFIX, "0.0.0"); assertNotNull(cookbook, "Cookbook not found: " + PREFIX); assertNotNull(api.updateCookbook(PREFIX, "0.0.0", cookbook), "Updated cookbook was null"); } @Test(dependsOnMethods = { "testCreateNewCookbook", "testUpdateCookbook" }) public void testDeleteCookbook() throws Exception { assertNotNull(api.deleteCookbook(PREFIX, "0.0.0"), "Deleted cookbook was null"); } @Test public void testCreateClient() throws Exception { api.deleteClient(PREFIX); String credential = Pems.pem(api.createClient(PREFIX).getPrivateKey()); assertClientCreated(PREFIX, credential); } @Test public void testCreateAdminClient() throws Exception { api.deleteClient(ADMIN_PREFIX); String credential = Pems.pem(api.createClient(ADMIN_PREFIX, CreateClientOptions.Builder.admin()).getPrivateKey()); assertClientCreated(ADMIN_PREFIX, credential); } @Test(dependsOnMethods = "testCreateClient") public void testGenerateKeyForClient() throws Exception { String credential = Pems.pem(api.generateKeyForClient(PREFIX).getPrivateKey()); assertClientCreated(PREFIX, credential); } @Test public void testListNodes() throws Exception { Set nodes = api.listNodes(); assertNotNull(nodes, "No nodes were found"); } @Test(dependsOnMethods = "testCreateRole") public void testCreateNode() throws Exception { api.deleteNode(PREFIX); api.createNode(Node.builder().name(PREFIX).runListElement("role[" + PREFIX + "]").environment("_default").build()); Node node = api.getNode(PREFIX); // TODO check recipes assertNotNull(node, "Created node should not be null"); Set nodes = api.listNodes(); assertTrue(nodes.contains(PREFIX), String.format("node %s not in %s", PREFIX, nodes)); } @Test(dependsOnMethods = "testCreateNode") public void testUpdateNode() throws Exception { for (String nodename : api.listNodes()) { Node node = api.getNode(nodename); api.updateNode(node); } } @Test public void testListRoles() throws Exception { Set roles = api.listRoles(); assertNotNull(roles, "Role list was null"); } @Test public void testCreateRole() throws Exception { String env1 = "env1"; String env2 = "env2"; String env1Alpha = "recipe[env1.alpha]"; String env2Alpha = "recipe[env2.alpha]"; String env2Bravo = "recipe[env2.bravo]"; api.deleteRole(PREFIX); api.createRole(Role.builder().name(PREFIX).runListElement("recipe[java]") .envRunListElement(env1, env1Alpha) .envRunListElement(env2, env2Alpha) .envRunListElement(env2, env2Bravo) .build()); Role role = api.getRole(PREFIX); assertNotNull(role, "Created role should not be null"); assertEquals(role.getName(), PREFIX); assertEquals(role.getRunList(), Collections.singleton("recipe[java]")); assertNotNull(role.getEnvRunList(), "envRunList should not be null"); assertEquals(role.getEnvRunList().size(), 2, "envRunList.size should be 2"); verifyRunListForEnvironment(role.getEnvRunList(), env1, env1Alpha); verifyRunListForEnvironment(role.getEnvRunList(), env2, env2Alpha, env2Bravo); } @Test(dependsOnMethods = "testCreateRole") public void testUpdateRole() throws Exception { for (String rolename : api.listRoles()) { Role role = api.getRole(rolename); api.updateRole(role); } } @Test public void testListDatabags() throws Exception { Set databags = api.listDatabags(); assertNotNull(databags, "Data bag list was null"); } @Test public void testCreateDatabag() throws Exception { api.deleteDatabag(PREFIX); api.createDatabag(PREFIX); } @Test(dependsOnMethods = "testCreateDatabagItem") public void testListDatabagItems() throws Exception { Set databagItems = api.listDatabagItems(PREFIX); assertNotNull(databagItems, "Data bag item list was null"); } @Test(dependsOnMethods = "testCreateDatabag") public void testCreateDatabagItem() throws Exception { Properties config = new Properties(); config.setProperty("foo", "bar"); api.deleteDatabagItem(PREFIX, PREFIX); DatabagItem databagItem = api.createDatabagItem(PREFIX, new DatabagItem("config", json.toJson(config))); databagitemId = databagItem.getId(); assertNotNull(databagItem, "Created data bag item should not be null"); assertEquals(databagItem.getId(), "config"); // The databagItem json contains extra keys: (the name and the type if the // item) Properties props = json.fromJson(databagItem.toString(), Properties.class); for (Object key : config.keySet()) { assertTrue(props.containsKey(key)); assertEquals(config.get(key), props.get(key)); } } @Test(dependsOnMethods = "testCreateDatabagItem") public void testUpdateDatabagItem() throws Exception { for (String databagItemId : api.listDatabagItems(PREFIX)) { DatabagItem databagItem = api.getDatabagItem(PREFIX, databagItemId); api.updateDatabagItem(PREFIX, databagItem); } } @Test(dependsOnMethods = "testSearchDatabagWithOptions") public void testDeleteDatabagItem() throws Exception { for (String databagItemId : api.listDatabagItems(PREFIX)) { DatabagItem databagItem = api.deleteDatabagItem(PREFIX, databagItemId); assertNotNull(databagItem, "Deleted data bag item should not be null"); assertEquals(databagItem.getId(), databagItemId, "Deleted data bag item id must match the original id"); assertNull(api.getDatabagItem(PREFIX, databagItemId), "Data bag item should not exist"); } } @Test public void testListSearchIndexes() throws Exception { Set indexes = api.listSearchIndexes(); assertNotNull(indexes, "The index list should not be null"); assertTrue(indexes.contains("node")); assertTrue(indexes.contains("client")); assertTrue(indexes.contains("role")); } @Test public void testSearchNodes() throws Exception { SearchResult results = api.searchNodes(); assertNotNull(results, "Node result list should not be null"); } @Test(dependsOnMethods = { "testListSearchIndexes", "testCreateNode" }) public void testSearchNodesWithOptions() throws Exception { Predicate waitForIndex = retry(new Predicate() { @Override public boolean apply(SearchOptions input) { SearchResult results = api.searchNodes(input); assertNotNull(results); if (results.size() > 0) { assertEquals(results.size(), 1); assertEquals(results.iterator().next().getName(), PREFIX); return true; } else { // The index may still not be populated return false; } } }, maxWaitForIndexInMs, 5000L, MILLISECONDS); SearchOptions options = SearchOptions.Builder.query("name:" + PREFIX); assertTrue(waitForIndex.apply(options)); } @Test public void testSearchClients() throws Exception { SearchResult results = api.searchClients(); assertNotNull(results, "Client result list should not be null"); } @Test(dependsOnMethods = { "testListSearchIndexes", "testCreateClient" }) public void testSearchClientsWithOptions() throws Exception { Predicate waitForIndex = retry(new Predicate() { @Override public boolean apply(SearchOptions input) { SearchResult results = api.searchClients(input); assertNotNull(results); if (results.size() > 0) { assertEquals(results.size(), 1); assertEquals(results.iterator().next().getName(), PREFIX); return true; } else { // The index may still not be populated return false; } } }, maxWaitForIndexInMs, 5000L, MILLISECONDS); SearchOptions options = SearchOptions.Builder.query("name:" + PREFIX); assertTrue(waitForIndex.apply(options)); } @Test public void testSearchRoles() throws Exception { SearchResult results = api.searchRoles(); assertNotNull(results, "Role result list should not be null"); } @Test(dependsOnMethods = { "testListSearchIndexes", "testCreateRole" }) public void testSearchRolesWithOptions() throws Exception { Predicate waitForIndex = retry(new Predicate() { @Override public boolean apply(SearchOptions input) { SearchResult results = api.searchRoles(input); assertNotNull(results); if (results.size() > 0) { assertEquals(results.size(), 1); assertEquals(results.iterator().next().getName(), PREFIX); return true; } else { // The index may still not be populated return false; } } }, maxWaitForIndexInMs, 5000L, MILLISECONDS); SearchOptions options = SearchOptions.Builder.query("name:" + PREFIX); assertTrue(waitForIndex.apply(options)); } @Test(dependsOnMethods = { "testListSearchIndexes", "testCreateDatabagItem" }) public void testSearchDatabag() throws Exception { SearchResult results = api.searchDatabagItems(PREFIX); assertNotNull(results, "Data bag item result list should not be null"); } @Test(dependsOnMethods = { "testListSearchIndexes", "testCreateDatabagItem" }) public void testSearchDatabagWithOptions() throws Exception { Predicate waitForIndex = retry(new Predicate() { @Override public boolean apply(SearchOptions input) { SearchResult results = api.searchDatabagItems(PREFIX, input); assertNotNull(results); if (results.size() > 0) { assertEquals(results.size(), 1); assertEquals(results.iterator().next().getId(), databagitemId); return true; } else { // The index may still not be populated return false; } } }, maxWaitForIndexInMs, 5000L, MILLISECONDS); SearchOptions options = SearchOptions.Builder.query("id:" + databagitemId); assertTrue(waitForIndex.apply(options)); } @Test(expectedExceptions = ResourceNotFoundException.class, dependsOnMethods = "testListSearchIndexes") public void testSearchDatabagNotFound() throws Exception { SearchResult results = api.searchDatabagItems("whoopie"); assertNotNull(results, "Data bag item result list should not be null"); } @Test public void testCreateEnvironment() { api.deleteEnvironment(PREFIX); api.createEnvironment(Environment.builder().name(PREFIX).description(PREFIX).build()); Environment env = api.getEnvironment(PREFIX); assertNotNull(env, "Created environment should not be null"); assertEquals(env.getName(), PREFIX); assertEquals(env.getDescription(), PREFIX); } @Test(dependsOnMethods = "testCreateEnvironment") public void testListEnvironment() { Set envList = api.listEnvironments(); assertNotNull(envList, "Environment list was null"); assertTrue(envList.contains(PREFIX)); } @Test(dependsOnMethods = "testCreateEnvironment") public void testSearchEnvironments() throws Exception { SearchResult results = api.searchEnvironments(); assertNotNull(results, "Environment result list was null"); } @Test(dependsOnMethods = { "testListSearchIndexes", "testCreateEnvironment" }) public void testSearchEnvironmentsWithOptions() throws Exception { Predicate waitForIndex = retry(new Predicate() { @Override public boolean apply(SearchOptions input) { SearchResult results = api.searchEnvironments(input); assertNotNull(results); if (results.size() > 0) { assertEquals(results.size(), 1); assertEquals(results.iterator().next().getName(), PREFIX); return true; } else { // The index may still not be populated return false; } } }, maxWaitForIndexInMs, 5000L, MILLISECONDS); SearchOptions options = SearchOptions.Builder.query("name:" + PREFIX); assertTrue(waitForIndex.apply(options)); } @Test(dependsOnMethods = "testCreateEnvironment") public void testListRecipesInEnvironment() { Set recipeList = api.listRecipesInEnvironment(PREFIX); assertTrue(!recipeList.isEmpty()); } @Test(dependsOnMethods = "testCreateEnvironment") public void testListNodesInEnvironment() { api.deleteNode(ENV_NODE); api.createNode(Node.builder().name(ENV_NODE).runListElement("role[" + PREFIX + "]").environment(PREFIX).build()); Node node = api.getNode(ENV_NODE); assertNotNull(node, "Created node should not be null"); Set nodeList = api.listNodesInEnvironment(PREFIX); assertTrue(!nodeList.isEmpty()); } @Test(dependsOnMethods = "testCreateNewCookbook") public void testListCookbooksInEnvironment() throws Exception { Set cookbooks = api.listCookbooksInEnvironment("_default"); assertTrue(any(cookbooks, new Predicate() { @Override public boolean apply(CookbookDefinition input) { return PREFIX.equals(input.getName()); }}), String.format("Cookbook %s not in %s", PREFIX, cookbooks)); } @AfterClass(groups = { "live", "integration" }) @Override public void tearDown() { api.deleteClient(PREFIX); api.deleteClient(ADMIN_PREFIX); api.deleteNode(PREFIX); api.deleteNode(ENV_NODE); api.deleteRole(PREFIX); api.deleteDatabag(PREFIX); api.deleteEnvironment(PREFIX); super.tearDown(); } private void assertClientCreated(String identity, String credential) { Properties overrides = super.setupProperties(); overrides.setProperty(provider + ".identity", identity); overrides.setProperty(provider + ".credential", credential); ChefApi clientApi = create(overrides, setupModules()); try { Client client = clientApi.getClient(identity); assertNotNull(client, "Client not found: " + identity); } finally { closeQuietly(clientApi); } } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/ChefApiMetadataTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef; import org.jclouds.View; import org.jclouds.rest.internal.BaseHttpApiMetadataTest; import org.testng.annotations.Test; import com.google.common.collect.ImmutableSet; import com.google.common.reflect.TypeToken; @Test(groups = "unit", testName = "ChefApiMetadataTest") public class ChefApiMetadataTest extends BaseHttpApiMetadataTest { // no config management abstraction, yet public ChefApiMetadataTest() { super(new ChefApiMetadata(), ImmutableSet.> of()); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/ChefApiTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef; import static com.google.common.io.BaseEncoding.base16; import static com.google.common.primitives.Bytes.asList; import static org.jclouds.reflect.Reflection2.method; import static org.testng.Assert.assertEquals; import java.io.IOException; import java.net.URI; import java.util.Properties; import java.util.Set; import org.jclouds.Constants; import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404; import org.jclouds.Fallbacks.NullOnNotFoundOr404; import org.jclouds.Fallbacks.VoidOnNotFoundOr404; import org.jclouds.apis.ApiMetadata; import org.jclouds.chef.config.ChefHttpApiModule; import org.jclouds.chef.domain.CookbookVersion; import org.jclouds.chef.domain.DatabagItem; import org.jclouds.chef.domain.Node; import org.jclouds.chef.domain.Resource; import org.jclouds.chef.domain.Role; import org.jclouds.chef.filters.SignedHeaderAuth; import org.jclouds.chef.filters.SignedHeaderAuthTest; import org.jclouds.chef.functions.ParseCookbookVersionsFromJson; import org.jclouds.chef.functions.ParseKeySetFromJson; import org.jclouds.chef.functions.ParseSearchClientsFromJson; import org.jclouds.chef.functions.ParseSearchDatabagFromJson; import org.jclouds.chef.functions.ParseSearchNodesFromJson; import org.jclouds.chef.options.CreateClientOptions; import org.jclouds.chef.options.SearchOptions; import org.jclouds.date.TimeStamp; import org.jclouds.fallbacks.MapHttp4xxCodesToExceptions; import org.jclouds.http.HttpRequest; import org.jclouds.http.functions.ParseFirstJsonValueNamed; import org.jclouds.http.functions.ParseJson; import org.jclouds.http.functions.ReleasePayloadAndReturn; import org.jclouds.http.functions.ReturnInputStream; import org.jclouds.io.Payload; import org.jclouds.io.payloads.StringPayload; import org.jclouds.reflect.Invocation; import org.jclouds.rest.ConfiguresHttpApi; import org.jclouds.rest.internal.BaseRestAnnotationProcessingTest; import org.jclouds.rest.internal.GeneratedHttpRequest; import org.testng.annotations.Test; import com.google.common.base.Supplier; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.reflect.Invokable; import com.google.inject.Module; /** * Tests annotation parsing of {@code ChefApi}. */ @Test(groups = { "unit" }) public class ChefApiTest extends BaseRestAnnotationProcessingTest { public void testCommitSandbox() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "commitSandbox", String.class, boolean.class); GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, ImmutableList. of("0189e76ccc476701d6b374e5a1a27347", true))); assertRequestLineEquals(httpRequest, "PUT http://localhost:4000/sandboxes/0189e76ccc476701d6b374e5a1a27347 HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApiMetadata.DEFAULT_API_VERSION + "-test\n"); assertPayloadEquals(httpRequest, "{\"is_completed\":true}", "application/json", false); assertResponseParserClassEquals(method, httpRequest, ParseJson.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, null); checkFilters(httpRequest); } public void testCreateUploadSandboxForChecksums() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "createUploadSandboxForChecksums", Set.class); GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, ImmutableList . of(ImmutableSet.of(asList(base16().lowerCase().decode("0189e76ccc476701d6b374e5a1a27347")), asList(base16().lowerCase().decode("0c5ecd7788cf4f6c7de2a57193897a6c")), asList(base16().lowerCase() .decode("1dda05ed139664f1f89b9dec482b77c0")))))); assertRequestLineEquals(httpRequest, "POST http://localhost:4000/sandboxes HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApiMetadata.DEFAULT_API_VERSION + "-test\n"); assertPayloadEquals(httpRequest, "{\"checksums\":{\"0189e76ccc476701d6b374e5a1a27347\":null,\"0c5ecd7788cf4f6c7de2a57193897a6c\":null," + "\"1dda05ed139664f1f89b9dec482b77c0\":null}}", "application/json", false); assertResponseParserClassEquals(method, httpRequest, ParseJson.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, null); checkFilters(httpRequest); } public void testUploadContent() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "uploadContent", URI.class, Payload.class); GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, ImmutableList. of(URI.create("http://foo/bar"), new StringPayload("{\"foo\": \"bar\"}")))); assertRequestLineEquals(httpRequest, "PUT http://foo/bar HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApiMetadata.DEFAULT_API_VERSION + "-test\n"); assertPayloadEquals(httpRequest, "{\"foo\": \"bar\"}", "application/x-binary", false); assertResponseParserClassEquals(method, httpRequest, ReleasePayloadAndReturn.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, null); checkFilters(httpRequest); } public void testGetCookbook() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "getCookbook", String.class, String.class); GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, ImmutableList. of("cookbook", "1.0.0"))); assertRequestLineEquals(httpRequest, "GET http://localhost:4000/cookbooks/cookbook/1.0.0 HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApiMetadata.DEFAULT_API_VERSION + "-test\n"); assertPayloadEquals(httpRequest, null, null, false); assertResponseParserClassEquals(method, httpRequest, ParseJson.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, NullOnNotFoundOr404.class); checkFilters(httpRequest); } public void testDeleteCookbook() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "deleteCookbook", String.class, String.class); GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, ImmutableList. of("cookbook", "1.0.0"))); assertRequestLineEquals(httpRequest, "DELETE http://localhost:4000/cookbooks/cookbook/1.0.0 HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApiMetadata.DEFAULT_API_VERSION + "-test\n"); assertPayloadEquals(httpRequest, null, null, false); assertResponseParserClassEquals(method, httpRequest, ParseJson.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, NullOnNotFoundOr404.class); checkFilters(httpRequest); } public void testUpdateCookbook() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "updateCookbook", String.class, String.class, CookbookVersion.class); GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, ImmutableList. of("cookbook", "1.0.1", CookbookVersion.builder("cookbook", "1.0.1").build()))); assertRequestLineEquals(httpRequest, "PUT http://localhost:4000/cookbooks/cookbook/1.0.1 HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApiMetadata.DEFAULT_API_VERSION + "-test\n"); assertPayloadEquals(httpRequest, "{\"name\":\"cookbook-1.0.1\",\"definitions\":[],\"attributes\":[],\"files\":[]," + "\"metadata\":{\"suggestions\":{},\"dependencies\":{},\"conflicting\":{},\"providing\":{}," + "\"platforms\":{},\"recipes\":{},\"replacing\":{}," + "\"groupings\":{},\"attributes\":{},\"recommendations\":{}}," + "\"providers\":[],\"cookbook_name\":\"cookbook\",\"resources\":[],\"templates\":[]," + "\"libraries\":[],\"version\":\"1.0.1\"," + "\"recipes\":[],\"root_files\":[],\"json_class\":\"Chef::CookbookVersion\"," + "\"chef_type\":\"cookbook_version\"}", "application/json", false); assertResponseParserClassEquals(method, httpRequest, ParseJson.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, null); checkFilters(httpRequest); } public void testListVersionsOfCookbook() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "listVersionsOfCookbook", String.class); GeneratedHttpRequest httpRequest = processor .apply(Invocation.create(method, ImmutableList. of("apache2"))); assertRequestLineEquals(httpRequest, "GET http://localhost:4000/cookbooks/apache2 HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApiMetadata.DEFAULT_API_VERSION + "-test\n"); assertPayloadEquals(httpRequest, null, null, false); assertResponseParserClassEquals(method, httpRequest, ParseCookbookVersionsFromJson.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class); checkFilters(httpRequest); } public void testDeleteClient() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "deleteClient", String.class); GeneratedHttpRequest httpRequest = processor .apply(Invocation.create(method, ImmutableList. of("client"))); assertRequestLineEquals(httpRequest, "DELETE http://localhost:4000/clients/client HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApiMetadata.DEFAULT_API_VERSION + "-test\n"); assertPayloadEquals(httpRequest, null, null, false); assertResponseParserClassEquals(method, httpRequest, ParseJson.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, NullOnNotFoundOr404.class); checkFilters(httpRequest); } public void testCreateApi() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "createClient", String.class); GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, ImmutableList. of("api"))); assertRequestLineEquals(httpRequest, "POST http://localhost:4000/clients HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApiMetadata.DEFAULT_API_VERSION + "-test\n"); assertPayloadEquals(httpRequest, "{\"name\":\"api\"}", "application/json", false); assertResponseParserClassEquals(method, httpRequest, ParseJson.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, null); checkFilters(httpRequest); } public void testCreateAdminApi() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "createClient", String.class, CreateClientOptions.class); GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, ImmutableList. of("api", CreateClientOptions.Builder.admin()))); assertRequestLineEquals(httpRequest, "POST http://localhost:4000/clients HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApiMetadata.DEFAULT_API_VERSION + "-test\n"); assertPayloadEquals(httpRequest, "{\"name\":\"api\",\"admin\":true}", "application/json", false); assertResponseParserClassEquals(method, httpRequest, ParseJson.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, null); checkFilters(httpRequest); } public void testGenerateKeyForClient() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "generateKeyForClient", String.class); GeneratedHttpRequest httpRequest = processor .apply(Invocation.create(method, ImmutableList. of("client"))); assertRequestLineEquals(httpRequest, "PUT http://localhost:4000/clients/client HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApiMetadata.DEFAULT_API_VERSION + "-test\n"); assertPayloadEquals(httpRequest, "{\"name\":\"client\", \"private_key\": true}", "application/json", false); assertResponseParserClassEquals(method, httpRequest, ParseJson.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, null); checkFilters(httpRequest); } public void testDeleteNode() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "deleteNode", String.class); GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, ImmutableList. of("node"))); assertRequestLineEquals(httpRequest, "DELETE http://localhost:4000/nodes/node HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApiMetadata.DEFAULT_API_VERSION + "-test\n"); assertPayloadEquals(httpRequest, null, null, false); assertResponseParserClassEquals(method, httpRequest, ParseJson.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, NullOnNotFoundOr404.class); checkFilters(httpRequest); } public void testCreateNode() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "createNode", Node.class); GeneratedHttpRequest httpRequest = processor.apply(Invocation.create( method, ImmutableList. of(Node.builder().name("testnode").runListElement("recipe[java]") .environment("_default").build()))); assertRequestLineEquals(httpRequest, "POST http://localhost:4000/nodes HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApiMetadata.DEFAULT_API_VERSION + "-test\n"); assertPayloadEquals(httpRequest, "{\"name\":\"testnode\",\"normal\":{},\"override\":{},\"default\":{},\"automatic\":{}," + "\"run_list\":[\"recipe[java]\"],\"chef_environment\":\"_default\",\"json_class\":\"Chef::Node\"," + "\"chef_type\":\"node\"}", "application/json", false); assertResponseParserClassEquals(method, httpRequest, ReleasePayloadAndReturn.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, null); checkFilters(httpRequest); } public void testUpdateNode() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "updateNode", Node.class); GeneratedHttpRequest httpRequest = processor.apply(Invocation.create( method, ImmutableList. of(Node.builder().name("testnode").runListElement("recipe[java]") .environment("_default").build()))); assertRequestLineEquals(httpRequest, "PUT http://localhost:4000/nodes/testnode HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApiMetadata.DEFAULT_API_VERSION + "-test\n"); assertPayloadEquals(httpRequest, "{\"name\":\"testnode\",\"normal\":{},\"override\":{},\"default\":{},\"automatic\":{}," + "\"run_list\":[\"recipe[java]\"],\"chef_environment\":\"_default\",\"json_class\":\"Chef::Node\"," + "\"chef_type\":\"node\"}", "application/json", false); assertResponseParserClassEquals(method, httpRequest, ParseJson.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, null); checkFilters(httpRequest); } public void testDeleteRole() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "deleteRole", String.class); GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, ImmutableList. of("role"))); assertRequestLineEquals(httpRequest, "DELETE http://localhost:4000/roles/role HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApiMetadata.DEFAULT_API_VERSION + "-test\n"); assertPayloadEquals(httpRequest, null, null, false); assertResponseParserClassEquals(method, httpRequest, ParseJson.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, NullOnNotFoundOr404.class); checkFilters(httpRequest); } public void testCreateRole() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "createRole", Role.class); GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, ImmutableList. of(Role.builder().name("testrole").runListElement("recipe[java]") .envRunListElement("erl.one", "erl.one.alpha") .envRunListElement("erl.one", "erl.one.bravo") .envRunListElement("erl.two", "erl.two.alpha") .envRunListElement("erl.two", "erl.two.bravo") .build()))); assertRequestLineEquals(httpRequest, "POST http://localhost:4000/roles HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApiMetadata.DEFAULT_API_VERSION + "-test\n"); assertPayloadEquals(httpRequest, "{\"name\":\"testrole\",\"override_attributes\":{},\"default_attributes\":{}," + "\"run_list\":[\"recipe[java]\"],\"env_run_lists\":{\"erl.one\":[\"erl.one.alpha\",\"erl.one.bravo\"],\"erl.two\":[\"erl.two.alpha\",\"erl.two.bravo\"]},\"json_class\":\"Chef::Role\",\"chef_type\":\"role\"}", "application/json", false); assertResponseParserClassEquals(method, httpRequest, ReleasePayloadAndReturn.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, null); checkFilters(httpRequest); } public void testUpdateRole() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "updateRole", Role.class); GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, ImmutableList. of(Role.builder().name("testrole").runListElement("recipe[java]") .envRunListElement("erl.one", "erl.one.alpha") .envRunListElement("erl.one", "erl.one.bravo") .envRunListElement("erl.two", "erl.two.alpha") .envRunListElement("erl.two", "erl.two.bravo") .build()))); assertRequestLineEquals(httpRequest, "PUT http://localhost:4000/roles/testrole HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApiMetadata.DEFAULT_API_VERSION + "-test\n"); assertPayloadEquals(httpRequest, "{\"name\":\"testrole\",\"override_attributes\":{},\"default_attributes\":{}," + "\"run_list\":[\"recipe[java]\"],\"env_run_lists\":{\"erl.one\":[\"erl.one.alpha\",\"erl.one.bravo\"],\"erl.two\":[\"erl.two.alpha\",\"erl.two.bravo\"]},\"json_class\":\"Chef::Role\",\"chef_type\":\"role\"}", "application/json", false); assertResponseParserClassEquals(method, httpRequest, ParseJson.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, null); checkFilters(httpRequest); } public void testDeleteDatabag() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "deleteDatabag", String.class); GeneratedHttpRequest httpRequest = processor .apply(Invocation.create(method, ImmutableList. of("databag"))); assertRequestLineEquals(httpRequest, "DELETE http://localhost:4000/data/databag HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApiMetadata.DEFAULT_API_VERSION + "-test\n"); assertPayloadEquals(httpRequest, null, null, false); assertResponseParserClassEquals(method, httpRequest, ReleasePayloadAndReturn.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, VoidOnNotFoundOr404.class); checkFilters(httpRequest); } public void testCreateDatabag() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "createDatabag", String.class); GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, ImmutableList. of("name"))); assertRequestLineEquals(httpRequest, "POST http://localhost:4000/data HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApiMetadata.DEFAULT_API_VERSION + "-test\n"); assertPayloadEquals(httpRequest, "{\"name\":\"name\"}", "application/json", false); assertResponseParserClassEquals(method, httpRequest, ReleasePayloadAndReturn.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, null); checkFilters(httpRequest); } public void testDeleteDatabagItem() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "deleteDatabagItem", String.class, String.class); GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, ImmutableList. of("name", "databagItem"))); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApiMetadata.DEFAULT_API_VERSION + "-test\n"); assertPayloadEquals(httpRequest, null, null, false); assertResponseParserClassEquals(method, httpRequest, ParseFirstJsonValueNamed.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, NullOnNotFoundOr404.class); checkFilters(httpRequest); } @Test(expectedExceptions = IllegalArgumentException.class) public void testCreateDatabagItemThrowsIllegalArgumentOnPrimitive() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "createDatabagItem", String.class, DatabagItem.class); GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, ImmutableList. of("name", new DatabagItem("id", "100")))); assertRequestLineEquals(httpRequest, "POST http://localhost:4000/data/name HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApiMetadata.DEFAULT_API_VERSION + "-test\n"); assertPayloadEquals( httpRequest, "{\"name\":\"testdatabagItem\",\"override_attributes\":{},\"default_attributes\":{}," + "\"run_list\":[\"recipe[java]\"],\"json_class\":\"Chef::DatabagItem\",\"chef_type\":\"databagItem\"}", "application/json", false); assertResponseParserClassEquals(method, httpRequest, ParseJson.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, null); checkFilters(httpRequest); } @Test(expectedExceptions = IllegalArgumentException.class) public void testCreateDatabagItemThrowsIllegalArgumentOnWrongId() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "createDatabagItem", String.class, DatabagItem.class); GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, ImmutableList. of("name", new DatabagItem("id", "{\"id\": \"item1\",\"my_key\": \"my_data\"}")))); assertRequestLineEquals(httpRequest, "POST http://localhost:4000/data/name HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApiMetadata.DEFAULT_API_VERSION + "-test\n"); assertPayloadEquals( httpRequest, "{\"name\":\"testdatabagItem\",\"override_attributes\":{},\"default_attributes\":{}," + "\"run_list\":[\"recipe[java]\"],\"json_class\":\"Chef::DatabagItem\",\"chef_type\":\"databagItem\"}", "application/json", false); assertResponseParserClassEquals(method, httpRequest, ParseJson.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, null); checkFilters(httpRequest); } public void testCreateDatabagItem() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "createDatabagItem", String.class, DatabagItem.class); GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, ImmutableList. of("name", new DatabagItem("id", "{\"id\": \"id\",\"my_key\": \"my_data\"}")))); assertRequestLineEquals(httpRequest, "POST http://localhost:4000/data/name HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApiMetadata.DEFAULT_API_VERSION + "-test\n"); assertPayloadEquals(httpRequest, "{\"id\": \"id\",\"my_key\": \"my_data\"}", "application/json", false); assertResponseParserClassEquals(method, httpRequest, ParseJson.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, null); checkFilters(httpRequest); } public void testCreateDatabagItemEvenWhenUserForgotId() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "createDatabagItem", String.class, DatabagItem.class); GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, ImmutableList. of("name", new DatabagItem("id", "{\"my_key\": \"my_data\"}")))); assertRequestLineEquals(httpRequest, "POST http://localhost:4000/data/name HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApiMetadata.DEFAULT_API_VERSION + "-test\n"); assertPayloadEquals(httpRequest, "{\"id\":\"id\",\"my_key\": \"my_data\"}", "application/json", false); assertResponseParserClassEquals(method, httpRequest, ParseJson.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, null); checkFilters(httpRequest); } public void testUpdateDatabagItem() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "updateDatabagItem", String.class, DatabagItem.class); GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, ImmutableList. of("name", new DatabagItem("id", "{\"my_key\": \"my_data\"}")))); assertRequestLineEquals(httpRequest, "PUT http://localhost:4000/data/name/id HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApiMetadata.DEFAULT_API_VERSION + "-test\n"); assertPayloadEquals(httpRequest, "{\"id\":\"id\",\"my_key\": \"my_data\"}", "application/json", false); assertResponseParserClassEquals(method, httpRequest, ParseJson.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, null); checkFilters(httpRequest); } public void testListDatabagItems() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "listDatabagItems", String.class); GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, ImmutableList. of("name"))); assertRequestLineEquals(httpRequest, "GET http://localhost:4000/data/name HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApiMetadata.DEFAULT_API_VERSION + "-test\n"); assertPayloadEquals(httpRequest, null, null, false); assertResponseParserClassEquals(method, httpRequest, ParseKeySetFromJson.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class); checkFilters(httpRequest); } public void testListSearchIndexes() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "listSearchIndexes"); GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, ImmutableList.of())); assertRequestLineEquals(httpRequest, "GET http://localhost:4000/search HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApiMetadata.DEFAULT_API_VERSION + "-test\n"); assertPayloadEquals(httpRequest, null, null, false); assertResponseParserClassEquals(method, httpRequest, ParseKeySetFromJson.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class); checkFilters(httpRequest); } public void testSearchClients() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "searchClients"); GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, ImmutableList.of())); assertRequestLineEquals(httpRequest, "GET http://localhost:4000/search/client HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApiMetadata.DEFAULT_API_VERSION + "-test\n"); assertPayloadEquals(httpRequest, null, null, false); assertResponseParserClassEquals(method, httpRequest, ParseSearchClientsFromJson.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, MapHttp4xxCodesToExceptions.class); checkFilters(httpRequest); } public void testSearchClientsWithOptions() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "searchClients", SearchOptions.class); GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, ImmutableList. of(SearchOptions.Builder.query("text").rows(5)))); assertRequestLineEquals(httpRequest, "GET http://localhost:4000/search/client?q=text&rows=5 HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApiMetadata.DEFAULT_API_VERSION + "-test\n"); assertPayloadEquals(httpRequest, null, null, false); assertResponseParserClassEquals(method, httpRequest, ParseSearchClientsFromJson.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, MapHttp4xxCodesToExceptions.class); checkFilters(httpRequest); } public void testSearchNodes() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "searchNodes"); GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, ImmutableList.of())); assertRequestLineEquals(httpRequest, "GET http://localhost:4000/search/node HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApiMetadata.DEFAULT_API_VERSION + "-test\n"); assertPayloadEquals(httpRequest, null, null, false); assertResponseParserClassEquals(method, httpRequest, ParseSearchNodesFromJson.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, MapHttp4xxCodesToExceptions.class); checkFilters(httpRequest); } public void testSearchNodesWithOptions() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "searchNodes", SearchOptions.class); GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, ImmutableList. of(SearchOptions.Builder.query("foo:foo").start(3)))); assertRequestLineEquals(httpRequest, "GET http://localhost:4000/search/node?q=foo%3Afoo&start=3 HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApiMetadata.DEFAULT_API_VERSION + "-test\n"); assertPayloadEquals(httpRequest, null, null, false); assertResponseParserClassEquals(method, httpRequest, ParseSearchNodesFromJson.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, MapHttp4xxCodesToExceptions.class); checkFilters(httpRequest); } public void testSearchDatabagItems() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "searchDatabagItems", String.class); GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, ImmutableList. of("foo"))); assertRequestLineEquals(httpRequest, "GET http://localhost:4000/search/foo HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApiMetadata.DEFAULT_API_VERSION + "-test\n"); assertPayloadEquals(httpRequest, null, null, false); assertResponseParserClassEquals(method, httpRequest, ParseSearchDatabagFromJson.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, MapHttp4xxCodesToExceptions.class); checkFilters(httpRequest); } public void testSearchDatabagItemsWithOptions() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "searchDatabagItems", String.class, SearchOptions.class); GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, ImmutableList. of("foo", SearchOptions.Builder.query("bar").sort("name DESC")))); assertRequestLineEquals(httpRequest, "GET http://localhost:4000/search/foo?q=bar&sort=name%20DESC HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApiMetadata.DEFAULT_API_VERSION + "-test\n"); assertPayloadEquals(httpRequest, null, null, false); assertResponseParserClassEquals(method, httpRequest, ParseSearchDatabagFromJson.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, MapHttp4xxCodesToExceptions.class); checkFilters(httpRequest); } public void testGetResourceContents() throws SecurityException, NoSuchMethodException, IOException { Invokable method = method(ChefApi.class, "getResourceContents", Resource.class); GeneratedHttpRequest httpRequest = processor.apply(Invocation.create(method, ImmutableList. of(Resource.builder().name("test").url(URI.create("http://foo/bar")).build()))); assertRequestLineEquals(httpRequest, "GET http://foo/bar HTTP/1.1"); assertNonPayloadHeadersEqual(httpRequest, "Accept: application/json\nX-Chef-Version: " + ChefApiMetadata.DEFAULT_API_VERSION + "-test\n"); assertPayloadEquals(httpRequest, null, null, false); assertResponseParserClassEquals(method, httpRequest, ReturnInputStream.class); assertSaxResponseParserClassEquals(method, null); assertFallbackClassEquals(method, NullOnNotFoundOr404.class); checkFilters(httpRequest); } @Override protected void checkFilters(HttpRequest request) { assertEquals(request.getFilters().size(), 1); assertEquals(request.getFilters().get(0).getClass(), SignedHeaderAuth.class); } @Override protected Module createModule() { return new TestChefHttpApiModule(); } @Override protected Properties setupProperties() { Properties props = super.setupProperties(); props.put(Constants.PROPERTY_API_VERSION, ChefApiMetadata.DEFAULT_API_VERSION + "-test"); return props; } @ConfiguresHttpApi static class TestChefHttpApiModule extends ChefHttpApiModule { @Override protected String provideTimeStamp(@TimeStamp Supplier cache) { return "timestamp"; } } @Override public ApiMetadata createApiMetadata() { identity = "user"; credential = SignedHeaderAuthTest.PRIVATE_KEY; return new ChefApiMetadata(); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/binders/BindGroupToUpdateRequestJsonPayloadTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.binders; import static org.testng.Assert.assertEquals; import java.io.IOException; import java.net.URI; import org.jclouds.chef.ChefApiMetadata; import org.jclouds.chef.config.ChefParserModule; import org.jclouds.chef.domain.Group; import org.jclouds.http.HttpRequest; import org.jclouds.json.config.GsonModule; import org.jclouds.rest.annotations.ApiVersion; import org.jclouds.util.Strings2; import org.testng.annotations.Test; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; /** * Unit tests for the {@link BindGroupToUpdateRequestJsonPayload} class. */ @Test(groups = "unit", testName = "BindGroupToUpdateRequestJsonPayloadTest") public class BindGroupToUpdateRequestJsonPayloadTest { private Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION); } }, new ChefParserModule(), new GsonModule()); private BindGroupToUpdateRequestJsonPayload binder = injector.getInstance(BindGroupToUpdateRequestJsonPayload.class); @Test(expectedExceptions = NullPointerException.class) public void testInvalidNullInput() { HttpRequest request = HttpRequest.builder().method("POST").endpoint(URI.create("http://localhost")).build(); binder.bindToRequest(request, null); } @Test(expectedExceptions = IllegalArgumentException.class) public void testInvalidTypeInput() { HttpRequest request = HttpRequest.builder().method("POST").endpoint(URI.create("http://localhost")).build(); binder.bindToRequest(request, new Object()); } public void testBindOnlyName() throws IOException { HttpRequest request = HttpRequest.builder().method("POST").endpoint(URI.create("http://localhost")).build(); HttpRequest newRequest = binder.bindToRequest(request, Group.builder("foo").build()); String payload = Strings2.toStringAndClose(newRequest.getPayload().getInput()); assertEquals(payload, "{\"groupname\":\"foo\",\"actors\":{\"clients\":[],\"groups\":[],\"users\":[]}}"); } public void testBindNameAndLists() throws IOException { Group group = Group.builder("foo").client("nacx-validator").group("admins").user("nacx").build(); HttpRequest request = HttpRequest.builder().method("POST").endpoint(URI.create("http://localhost")).build(); HttpRequest newRequest = binder.bindToRequest(request, group); String payload = Strings2.toStringAndClose(newRequest.getPayload().getInput()); assertEquals(payload, "{\"groupname\":\"foo\",\"actors\":{\"clients\":[\"nacx-validator\"],\"groups\":[\"admins\"],\"users\":[\"nacx\"]}}"); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/binders/BindHexEncodedMD5sToJsonPayloadTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.binders; import static com.google.common.io.BaseEncoding.base16; import static com.google.common.primitives.Bytes.asList; import static org.testng.Assert.assertEquals; import java.io.File; import jakarta.ws.rs.HttpMethod; import org.jclouds.chef.ChefApiMetadata; import org.jclouds.chef.config.ChefParserModule; import org.jclouds.http.HttpRequest; import org.jclouds.json.config.GsonModule; import org.jclouds.rest.annotations.ApiVersion; import org.testng.annotations.Test; import com.google.common.collect.ImmutableSet; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; @Test(groups = { "unit" }) public class BindHexEncodedMD5sToJsonPayloadTest { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION); } }, new ChefParserModule(), new GsonModule()); BindChecksumsToJsonPayload binder = injector.getInstance(BindChecksumsToJsonPayload.class); @Test(expectedExceptions = IllegalArgumentException.class) public void testMustBeIterable() { HttpRequest request = HttpRequest.builder().method(HttpMethod.POST).endpoint("http://localhost").build(); binder.bindToRequest(request, new File("foo")); } public void testCorrect() { HttpRequest request = HttpRequest.builder().method(HttpMethod.POST).endpoint("http://localhost").build(); binder.bindToRequest(request, ImmutableSet.of(asList(base16().lowerCase().decode("abddef")), asList(base16().lowerCase().decode("1234")))); assertEquals(request.getPayload().getRawContent(), "{\"checksums\":{\"abddef\":null,\"1234\":null}}"); } @Test(expectedExceptions = { NullPointerException.class, IllegalStateException.class }) public void testNullIsBad() { HttpRequest request = HttpRequest.builder().method(HttpMethod.POST).endpoint("http://localhost").build(); binder.bindToRequest(request, null); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/binders/GroupNameTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.binders; import static org.testng.Assert.assertEquals; import java.io.IOException; import org.jclouds.chef.domain.Group; import org.testng.annotations.Test; /** * Unit tests for the {@link GroupName} class. */ @Test(groups = "unit", testName = "GroupNameTest") public class GroupNameTest { @Test(expectedExceptions = NullPointerException.class) public void testInvalidNullInput() { new GroupName().apply(null); } public void testApplyGroupName() throws IOException { assertEquals(new GroupName().apply(Group.builder("foo").build()), "foo"); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/config/ChefParserModuleTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.config; import static com.google.common.base.Objects.equal; import static org.testng.Assert.assertEquals; import java.lang.reflect.Type; import java.util.List; import java.util.Map; import org.jclouds.chef.config.ChefParserModule.KeepLastRepeatedKeyMapTypeAdapterFactory; import org.jclouds.json.internal.NullFilteringTypeAdapterFactories.ListTypeAdapterFactory; import org.testng.annotations.Test; import com.google.common.base.Objects; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.reflect.TypeToken; import com.google.gson.Gson; import com.google.gson.GsonBuilder; /** * Unit tests for the {@link ChefParserModule} class. */ @Test(groups = "unit", testName = "ChefParserModuleTest") public class ChefParserModuleTest { private static class KeyValue { private final String key; private final String value; private KeyValue(String key, String value) { this.key = key; this.value = value; } @Override public int hashCode() { return Objects.hashCode(key, value); } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null || getClass() != obj.getClass()) return false; KeyValue that = KeyValue.class.cast(obj); return equal(this.key, that.key) && equal(this.value, that.value); } } private Gson map = new GsonBuilder().registerTypeAdapterFactory(new KeepLastRepeatedKeyMapTypeAdapterFactory()) .create(); private Type mapType = new TypeToken>() { private static final long serialVersionUID = 1L; }.getType(); private Type mapkeyValueType = new TypeToken>() { private static final long serialVersionUID = 1L; }.getType(); public void testKeepLastRepeatedKeyMapTypeAdapter() { Map noNulls = map.fromJson("{\"value\":\"a test string!\"}", mapType); assertEquals(noNulls, ImmutableMap.of("value", "a test string!")); Map withNull = map.fromJson("{\"value\":null}", mapType); assertEquals(withNull, ImmutableMap.of()); Map withEmpty = map.fromJson("{\"value\":\"\"}", mapType); assertEquals(withEmpty, ImmutableMap.of("value", "")); Map keyValues = map.fromJson( "{\"i-foo\":{\"key\":\"i-foo\",\"value\":\"foo\"},\"i-bar\":{\"key\":\"i-bar\",\"value\":\"bar\"}}", mapkeyValueType); assertEquals(keyValues, ImmutableMap.of("i-foo", new KeyValue("i-foo", "foo"), "i-bar", new KeyValue("i-bar", "bar"))); Map duplicates = map .fromJson( "{\"i-foo\":{\"key\":\"i-foo\",\"value\":\"foo\", \"value\":\"foo2\"},\"i-bar\":{\"key\":\"i-bar\",\"value\":\"bar\",\"value\":\"bar2\"}}", mapkeyValueType); assertEquals(duplicates, ImmutableMap.of("i-foo", new KeyValue("i-foo", "foo2"), "i-bar", new KeyValue("i-bar", "bar2"))); } private Gson listInMap = new GsonBuilder().registerTypeAdapterFactory(new KeepLastRepeatedKeyMapTypeAdapterFactory()) .registerTypeAdapterFactory(new ListTypeAdapterFactory()).create(); private Type listInMapType = new TypeToken>>>() { private static final long serialVersionUID = 1L; }.getType(); public void testListInMap() { Map>> notNull = listInMap .fromJson("{\"value\":[{\"x\":\"y\",\"a\":\"b\"},{\"u\":\"v\"}]}", listInMapType); assertEquals(notNull, ImmutableMap.of("value", ImmutableList.of(ImmutableMap.of("x", "y", "a", "b"), ImmutableMap.of("u", "v")))); Map>> innerMapValueNull = listInMap .fromJson("{\"value\":[{\"x\":\"y\",\"a\":null},{\"u\":\"v\"}]}", listInMapType); assertEquals(innerMapValueNull, ImmutableMap.of("value", ImmutableList.of(ImmutableMap.of("x", "y"), ImmutableMap.of("u", "v")))); Map>> withNullInList = listInMap.fromJson("{\"value\":[null]}", listInMapType); assertEquals(withNullInList, ImmutableMap.of("value", ImmutableList.of())); Map>> withNullAsList = listInMap.fromJson("{\"parent\":null}", listInMapType); assertEquals(withNullAsList, ImmutableMap.of()); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/domain/RoleTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.domain; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNotEquals; import static org.testng.Assert.assertTrue; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import org.testng.annotations.Test; /** * Tests behaviors of {@code Role}. */ @Test(groups = { "unit" }) public class RoleTest { @Test(expectedExceptions = NullPointerException.class) public void canNotAddEnvRunListMapThatIsNull() { Role.builder().envRunList((Map>) null); } @Test(expectedExceptions = NullPointerException.class) public void canNotAddRunListForEnvironmentThatIsNull() { Role.builder().envRunList("does.not.matter", (List) null); } @Test(expectedExceptions = NullPointerException.class) public void canNotUseNullEnvNameWhenAddingEnvRunListEntry() { Role.builder().envRunListElement((String) null, "does.not.matter"); } @Test(expectedExceptions = NullPointerException.class) public void canNotUseNullEntryWhenAddingEnvRunListEntry() { Role.builder().envRunListElement("does.not.matter", (String) null); } public void multipleEnvRunListsCanBePopulated() { String env1 = "env1"; String env2 = "env2"; String env1Alpha = "env1.alpha"; String env2Alpha = "env2.alpha"; String env2Bravo = "env2.bravo"; Role role = Role.builder().envRunListElement(env1, env1Alpha).envRunListElement(env2, env2Alpha) .envRunListElement(env2, env2Bravo).build(); Map> envRunList = role.getEnvRunList(); assertNotNull(envRunList, "envRunList"); assertEquals(envRunList.size(), 2, "envRunList.size"); verifyRunListForEnvironment(envRunList, env1, env1Alpha); verifyRunListForEnvironment(envRunList, env2, env2Alpha, env2Bravo); } @Test(expectedExceptions = UnsupportedOperationException.class) public void envRunListOnNewlyBuiltRoleIsImmutable() { String env = "env"; Role role = Role.builder().envRunListElement(env, env + "1").build(); role.getEnvRunList().put("does.not.matter", new ArrayList()); } @Test(expectedExceptions = UnsupportedOperationException.class) public void envRunListEntriesOnNewlyBuiltRoleIsImmutable() { String env = "env"; Role role = Role.builder().envRunListElement(env, env + "1").build(); role.getEnvRunList().get(env).add("does.not.matter"); } public void rolesWithSameEnvRunListAreEqual() { String env = "env"; String entry = "entry"; Role role1 = Role.builder().envRunListElement(env, entry).build(); Role role2 = Role.builder().envRunListElement(env, entry).build(); assertEquals(role1.hashCode(), role2.hashCode(), "hashCodes should be equal"); assertEquals(role1, role2, "role1 should equal role2"); assertEquals(role2, role1, "role2 should equal role1"); } public void rolesWithDifferentEnvRunListAreNotEqual() { String env = "env"; String entry = "entry"; Role role1 = Role.builder().envRunListElement(env, entry.toUpperCase()).build(); Role role2 = Role.builder().envRunListElement(env, entry.toLowerCase()).build(); assertNotEquals(role1.hashCode(), role2.hashCode(), "hashCodes should not be equal"); assertNotEquals(role1, role2, "role1 should not equal role2"); assertNotEquals(role2, role1, "role2 should not equal role1"); } @Test(enabled = false) public static void verifyRunListForEnvironment(Map> envRunList, String envName, String... expectedEntries) { assertTrue(envRunList.containsKey(envName), "envRunList contains " + envName); assertEquals(envRunList.get(envName).size(), expectedEntries.length, "envRunList size for '" + envName); assertTrue(envRunList.get(envName).containsAll(Arrays.asList(expectedEntries)), "envRunList for e1 contains " + Arrays.asList(expectedEntries)); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/features/OrganizationApiExpectTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.features; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; import java.util.Set; import jakarta.ws.rs.core.MediaType; import org.jclouds.apis.ApiMetadata; import org.jclouds.chef.BaseChefApiExpectTest; import org.jclouds.chef.ChefApi; import org.jclouds.chef.ChefApiMetadata; import org.jclouds.chef.config.ChefHttpApiModule; import org.jclouds.chef.domain.Group; import org.jclouds.chef.domain.User; import org.jclouds.date.TimeStamp; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpResponseException; import org.jclouds.rest.ConfiguresHttpApi; import org.jclouds.rest.ResourceNotFoundException; import org.testng.annotations.Test; import com.google.common.base.Supplier; import com.google.inject.Module; /** * Expect tests for the {@link OrganizationApi} class. */ @Test(groups = "unit", testName = "OrganizationApiExpectTest") public class OrganizationApiExpectTest extends BaseChefApiExpectTest { public void testGetUserReturns2xx() { ChefApi api = requestSendsResponse( signed(HttpRequest.builder() // .method("GET") // .endpoint("http://localhost:4000/users/nacx") // .addHeader("X-Chef-Version", ChefApiMetadata.DEFAULT_API_VERSION) // .addHeader("Accept", MediaType.APPLICATION_JSON).build()), // HttpResponse.builder().statusCode(200) .payload(payloadFromResourceWithContentType("/user.json", MediaType.APPLICATION_JSON)) // .build()); User user = api.organizationApi().get().getUser("nacx"); assertEquals(user.getUsername(), "nacx"); assertEquals(user.getDisplayName(), "Ignasi Barrera"); } public void testGetUserReturns404() { ChefApi api = requestSendsResponse(signed(HttpRequest.builder() // .method("GET") // .endpoint("http://localhost:4000/users/foo") // .addHeader("X-Chef-Version", ChefApiMetadata.DEFAULT_API_VERSION) // .addHeader("Accept", MediaType.APPLICATION_JSON) // .build()), // HttpResponse.builder().statusCode(404).build()); assertNull(api.organizationApi().get().getUser("foo")); } public void testListGroups() { ChefApi api = requestSendsResponse( signed(HttpRequest.builder() // .method("GET") // .endpoint("http://localhost:4000/groups") // .addHeader("X-Chef-Version", ChefApiMetadata.DEFAULT_API_VERSION) // .addHeader("Accept", MediaType.APPLICATION_JSON).build()), // HttpResponse.builder().statusCode(200) .payload(payloadFromResourceWithContentType("/groups.json", MediaType.APPLICATION_JSON)) // .build()); Set groups = api.organizationApi().get().listGroups(); assertEquals(groups.size(), 5); assertTrue(groups.contains("admins")); } public void testGetGroupReturns2xx() { ChefApi api = requestSendsResponse( signed(HttpRequest.builder() // .method("GET") // .endpoint("http://localhost:4000/groups/admins") // .addHeader("X-Chef-Version", ChefApiMetadata.DEFAULT_API_VERSION) // .addHeader("Accept", MediaType.APPLICATION_JSON).build()), // HttpResponse.builder().statusCode(200) .payload(payloadFromResourceWithContentType("/group.json", MediaType.APPLICATION_JSON)) // .build()); Group group = api.organizationApi().get().getGroup("admins"); assertEquals(group.getName(), "admins"); assertEquals(group.getGroupname(), "admins"); } public void testGetGroupReturns404() { ChefApi api = requestSendsResponse(signed(HttpRequest.builder() // .method("GET") // .endpoint("http://localhost:4000/groups/foo") // .addHeader("X-Chef-Version", ChefApiMetadata.DEFAULT_API_VERSION) // .addHeader("Accept", MediaType.APPLICATION_JSON) // .build()), // HttpResponse.builder().statusCode(404).build()); assertNull(api.organizationApi().get().getGroup("foo")); } public void testCreateGroupReturns2xx() { ChefApi api = requestSendsResponse(signed(HttpRequest.builder() // .method("POST") // .endpoint("http://localhost:4000/groups") // .addHeader("X-Chef-Version", ChefApiMetadata.DEFAULT_API_VERSION) // .addHeader("Accept", MediaType.APPLICATION_JSON) // .payload(payloadFromStringWithContentType("{\"groupname\":\"foo\"}", MediaType.APPLICATION_JSON)) // .build()), // HttpResponse.builder().statusCode(201).build()); api.organizationApi().get().createGroup("foo"); } public void testDeleteGroupReturns2xx() { ChefApi api = requestSendsResponse(signed(HttpRequest.builder() // .method("DELETE") // .endpoint("http://localhost:4000/groups/foo") // .addHeader("X-Chef-Version", ChefApiMetadata.DEFAULT_API_VERSION) // .addHeader("Accept", MediaType.APPLICATION_JSON) // .build()), // HttpResponse.builder().statusCode(200).build()); api.organizationApi().get().deleteGroup("foo"); } @Test(expectedExceptions = HttpResponseException.class) public void testDeleteGroupFailsOn404() { ChefApi api = requestSendsResponse(signed(HttpRequest.builder() // .method("DELETE") // .endpoint("http://localhost:4000/groups/foo") // .addHeader("X-Chef-Version", ChefApiMetadata.DEFAULT_API_VERSION) // .addHeader("Accept", MediaType.APPLICATION_JSON) // .build()), // HttpResponse.builder().statusCode(404).build()); api.organizationApi().get().deleteGroup("foo"); } public void testUpdateGroupReturns2xx() { ChefApi api = requestSendsResponse(signed(HttpRequest.builder() // .method("PUT") // .endpoint("http://localhost:4000/groups/admins") // .addHeader("X-Chef-Version", ChefApiMetadata.DEFAULT_API_VERSION) // .addHeader("Accept", MediaType.APPLICATION_JSON) // .payload(payloadFromResourceWithContentType("/group-update.json", MediaType.APPLICATION_JSON)) // .build()), // HttpResponse.builder().statusCode(200).build()); Group group = Group.builder("admins").client("abiquo").group("admins").user("nacx").build(); api.organizationApi().get().updateGroup(group); } @Test(expectedExceptions = ResourceNotFoundException.class) public void testUpdateGroupFailsOn404() { ChefApi api = requestSendsResponse(signed(HttpRequest.builder() // .method("PUT") // .endpoint("http://localhost:4000/groups/admins") // .addHeader("X-Chef-Version", ChefApiMetadata.DEFAULT_API_VERSION) // .addHeader("Accept", MediaType.APPLICATION_JSON) // .payload(payloadFromResourceWithContentType("/group-update.json", MediaType.APPLICATION_JSON)) // .build()), // HttpResponse.builder().statusCode(404).build()); Group group = Group.builder("admins").client("abiquo").group("admins").user("nacx").build(); api.organizationApi().get().updateGroup(group); } @Override protected Module createModule() { return new TestChefHttpApiModule(); } @ConfiguresHttpApi static class TestChefHttpApiModule extends ChefHttpApiModule { @Override protected String provideTimeStamp(@TimeStamp Supplier cache) { return "timestamp"; } } @Override protected ApiMetadata createApiMetadata() { return new ChefApiMetadata(); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/features/OrganizationApiLiveTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.features; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; import java.util.Set; import java.util.UUID; import org.jclouds.chef.domain.Group; import org.jclouds.chef.domain.User; import org.jclouds.chef.internal.BaseChefLiveTest; import org.jclouds.rest.ResourceNotFoundException; import org.testng.SkipException; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; /** * Tests behavior of the OrganizationApi. */ @Test(groups = "live", singleThreaded = true, testName = "OrganizationApiLiveTest") public class OrganizationApiLiveTest extends BaseChefLiveTest { private static final String GROUP_NAME = System.getProperty("user.name") + "-jcloudstest"; private OrganizationApi orgApi; @BeforeMethod public void skipIfApiNotAvailable() { // Throwing SkipExceptions only works with @Test and @BeforeMethod methods if (!api.organizationApi().isPresent()) { throw new SkipException("Organization api not available in this Chef version"); } orgApi = api.organizationApi().get(); } public void testGetUser() { User user = orgApi.getUser(identity); assertEquals(user.getUsername(), identity); assertNotNull(user.getPublicKey()); } public void testGetUnexistingUser() { User user = orgApi.getUser(UUID.randomUUID().toString()); assertNull(user); } public void testListGroups() { Set groups = orgApi.listGroups(); assertNotNull(groups); assertFalse(groups.isEmpty()); } public void testGetUnexistingGroup() { Group group = orgApi.getGroup(UUID.randomUUID().toString()); assertNull(group); } public void testCreateGroup() { orgApi.createGroup(GROUP_NAME); Group group = orgApi.getGroup(GROUP_NAME); assertNotNull(group); assertEquals(group.getGroupname(), GROUP_NAME); } @Test(dependsOnMethods = "testCreateGroup") public void testUpdateGroup() { Group group = orgApi.getGroup(GROUP_NAME); Group updated = Group.builder(group.getGroupname()) // .actors(group.getActors()) // .orgname(group.getOrgname()) // .name(group.getName()) // .groups(group.getGroups()) // .client(group.getOrgname() + "-validator") // .user(identity) // .build(); orgApi.updateGroup(updated); group = orgApi.getGroup(GROUP_NAME); assertNotNull(group); assertTrue(group.getUsers().contains(identity)); assertTrue(group.getClients().contains(group.getOrgname() + "-validator")); } @Test(expectedExceptions = ResourceNotFoundException.class) public void testUpdateUnexistingGroup() { orgApi.updateGroup(Group.builder(UUID.randomUUID().toString()).build()); } @Test(dependsOnMethods = "testUpdateGroup", alwaysRun = true) public void testDeleteGroup() { orgApi.deleteGroup(GROUP_NAME); Group group = orgApi.getGroup(GROUP_NAME); assertNull(group); } @Test(expectedExceptions = ResourceNotFoundException.class) public void testDeleteUnexistingGroup() { orgApi.deleteGroup(UUID.randomUUID().toString()); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/filters/SignedHeaderAuthTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.filters; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEqualsNoOrder; import static org.testng.Assert.assertTrue; import java.io.IOException; import java.security.PrivateKey; import jakarta.inject.Provider; import jakarta.ws.rs.HttpMethod; import org.jclouds.ContextBuilder; import org.jclouds.chef.ChefApiMetadata; import org.jclouds.crypto.Crypto; import org.jclouds.domain.Credentials; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpUtils; import org.jclouds.http.internal.SignatureWire; import org.jclouds.logging.config.NullLoggingModule; import org.jclouds.rest.internal.BaseRestApiTest.MockModule; import org.jclouds.util.Strings2; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import com.google.common.base.Joiner; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; import com.google.common.base.Throwables; import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.Multimap; import com.google.common.net.HttpHeaders; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Module; import com.google.inject.TypeLiteral; @Test(groups = { "unit" }) public class SignedHeaderAuthTest { public static final String USER_ID = "spec-user"; public static final String BODY = "Spec Body"; // Base64.encode64(Digest::SHA1.digest("Spec Body")).chomp public static final String HASHED_BODY = "DFteJZPVv6WKdQmMqZUQUumUyRs="; public static final String TIMESTAMP_ISO8601 = "2009-01-01T12:00:00Z"; public static final String PATH = "/organizations/clownco"; // Base64.encode64(Digest::SHA1.digest("/organizations/clownco")).chomp public static final String HASHED_CANONICAL_PATH = "YtBWDn1blGGuFIuKksdwXzHU9oE="; public static final String REQUESTING_ACTOR_ID = "c0f8a68c52bffa1020222a56b23cccfa"; // Content hash is ???TODO public static final String X_OPS_CONTENT_HASH = "DFteJZPVv6WKdQmMqZUQUumUyRs="; public static final String[] X_OPS_AUTHORIZATION_LINES = new String[] { "jVHrNniWzpbez/eGWjFnO6lINRIuKOg40ZTIQudcFe47Z9e/HvrszfVXlKG4", "NMzYZgyooSvU85qkIUmKuCqgG2AIlvYa2Q/2ctrMhoaHhLOCWWoqYNMaEqPc", "3tKHE+CfvP+WuPdWk4jv4wpIkAz6ZLxToxcGhXmZbXpk56YTmqgBW2cbbw4O", "IWPZDHSiPcw//AYNgW1CCDptt+UFuaFYbtqZegcBd2n/jzcWODA7zL4KWEUy", "9q4rlh/+1tBReg60QdsmDRsw/cdO1GZrKtuCwbuD4+nbRdVBKv72rqHX9cu0", "utju9jzczCyB+sSAQWrxSsXB/b8vV2qs0l4VD2ML+w==" }; // We expect Mixlib::Authentication::SignedHeaderAuth//sign to return this // if passed the BODY above. public static final Multimap EXPECTED_SIGN_RESULT = ImmutableMultimap. builder() .put("X-Ops-Content-Hash", X_OPS_CONTENT_HASH).put("X-Ops-Userid", USER_ID).put("X-Ops-Sign", "version=1.0") .put("X-Ops-Authorization-1", X_OPS_AUTHORIZATION_LINES[0]) .put("X-Ops-Authorization-2", X_OPS_AUTHORIZATION_LINES[1]) .put("X-Ops-Authorization-3", X_OPS_AUTHORIZATION_LINES[2]) .put("X-Ops-Authorization-4", X_OPS_AUTHORIZATION_LINES[3]) .put("X-Ops-Authorization-5", X_OPS_AUTHORIZATION_LINES[4]) .put("X-Ops-Authorization-6", X_OPS_AUTHORIZATION_LINES[5]).put("X-Ops-Timestamp", TIMESTAMP_ISO8601).build(); // Content hash for empty string public static final String X_OPS_CONTENT_HASH_EMPTY = "2jmj7l5rSw0yVb/vlWAYkK/YBwk="; public static final Multimap EXPECTED_SIGN_RESULT_EMPTY = ImmutableMultimap . builder().put("X-Ops-Content-Hash", X_OPS_CONTENT_HASH_EMPTY).put("X-Ops-Userid", USER_ID) .put("X-Ops-Sign", "version=1.0") .put("X-Ops-Authorization-1", "N6U75kopDK64cEFqrB6vw+PnubnXr0w5LQeXnIGNGLRP2LvifwIeisk7QxEx") .put("X-Ops-Authorization-2", "mtpQOWAw8HvnWErjzuk9AvUsqVmWpv14ficvkaD79qsPMvbje+aLcIrCGT1P") .put("X-Ops-Authorization-3", "3d2uvf4w7iqwzrIscPnkxLR6o6pymR90gvJXDPzV7Le0jbfD8kmZ8AAK0sGG") .put("X-Ops-Authorization-4", "09F1ftW80bLatJTA66Cw2wBz261r6x/abZhIKFJFDWLzyQGJ8ZNOkUrDDtgI") .put("X-Ops-Authorization-5", "svLVXpOJKZZfKunsElpWjjsyNt3k8vpI1Y4ANO8Eg2bmeCPeEK+YriGm5fbC") .put("X-Ops-Authorization-6", "DzWNPylHJqMeGKVYwGQKpg62QDfe5yXh3wZLiQcXow==") .put("X-Ops-Timestamp", TIMESTAMP_ISO8601).build(); public static final String PUBLIC_KEY; public static final String PRIVATE_KEY; static { try { PUBLIC_KEY = Strings2.toStringAndClose(SignedHeaderAuthTest.class.getResourceAsStream("/pubkey.txt")); PRIVATE_KEY = Strings2.toStringAndClose(SignedHeaderAuthTest.class.getResourceAsStream("/privkey.txt")); } catch (IOException e) { throw Throwables.propagate(e); } } @Test void canonicalizedPathRemovesMultipleSlashes() { assertEquals(signing_obj.canonicalPath("///"), "/"); } @Test void canonicalizedPathRemovesTrailingSlash() { assertEquals(signing_obj.canonicalPath("/path/"), "/path"); } @Test void shouldGenerateTheCorrectStringToSignAndSignature() { HttpRequest request = HttpRequest.builder().method(HttpMethod.POST).endpoint("http://localhost/" + PATH) .payload(BODY).build(); String expected_string_to_sign = new StringBuilder().append("Method:POST").append("\n").append("Hashed Path:") .append(HASHED_CANONICAL_PATH).append("\n").append("X-Ops-Content-Hash:").append(HASHED_BODY).append("\n") .append("X-Ops-Timestamp:").append(TIMESTAMP_ISO8601).append("\n").append("X-Ops-UserId:").append(USER_ID) .toString(); assertEquals(signing_obj.createStringToSign("POST", HASHED_CANONICAL_PATH, HASHED_BODY, TIMESTAMP_ISO8601), expected_string_to_sign); assertEquals(signing_obj.sign(expected_string_to_sign), Joiner.on("").join(X_OPS_AUTHORIZATION_LINES)); request = signing_obj.filter(request); Multimap headersWithoutContentLength = LinkedHashMultimap.create(request.getHeaders()); headersWithoutContentLength.removeAll(HttpHeaders.CONTENT_LENGTH); assertEqualsNoOrder(headersWithoutContentLength.values().toArray(), EXPECTED_SIGN_RESULT.values().toArray()); } @Test void shouldGenerateTheCorrectStringToSignAndSignatureWithNoBody() { HttpRequest request = HttpRequest.builder().method(HttpMethod.DELETE).endpoint("http://localhost/" + PATH) .build(); request = signing_obj.filter(request); Multimap headersWithoutContentLength = LinkedHashMultimap.create(request.getHeaders()); assertEqualsNoOrder(headersWithoutContentLength.entries().toArray(), EXPECTED_SIGN_RESULT_EMPTY.entries() .toArray()); } @Test void shouldNotChokeWhenSigningARequestForAResourceWithALongName() { StringBuilder path = new StringBuilder("nodes/"); for (int i = 0; i < 100; i++) path.append('A'); HttpRequest request = HttpRequest.builder().method(HttpMethod.PUT) .endpoint("http://localhost/" + path.toString()).payload(BODY).build(); signing_obj.filter(request); } @Test void shouldReplacePercentage3FWithQuestionMarkAtUrl() { StringBuilder path = new StringBuilder("nodes/"); path.append("test/cookbooks/myCookBook%3Fnum_versions=5"); HttpRequest request = HttpRequest.builder().method(HttpMethod.GET) .endpoint("http://localhost/" + path.toString()).payload(BODY).build(); request = signing_obj.filter(request); assertTrue(request.getRequestLine().contains("?num_versions=5")); } private SignedHeaderAuth signing_obj; /** * before class, as we need to ensure that the filter is threadsafe. * * @throws IOException * */ @BeforeClass protected void createFilter() throws IOException { Injector injector = ContextBuilder.newBuilder(new ChefApiMetadata()).credentials(USER_ID, PRIVATE_KEY) .modules(ImmutableSet. of(new MockModule(), new NullLoggingModule())).buildInjector(); HttpUtils utils = injector.getInstance(HttpUtils.class); Crypto crypto = injector.getInstance(Crypto.class); Supplier privateKey = injector.getInstance(Key.get(new TypeLiteral>() { })); signing_obj = new SignedHeaderAuth(new SignatureWire(), Suppliers.ofInstance(new Credentials(USER_ID, PRIVATE_KEY)), privateKey, new Provider() { @Override public String get() { return TIMESTAMP_ISO8601; } }, utils, crypto); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/functions/BootstrapConfigForGroupTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.functions; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; import static org.testng.Assert.assertEquals; import java.io.IOException; import org.jclouds.chef.ChefApi; import org.jclouds.chef.domain.BootstrapConfig; import org.jclouds.chef.domain.Client; import org.jclouds.chef.domain.DatabagItem; import org.jclouds.chef.domain.BootstrapConfig.SSLVerifyMode; import org.jclouds.json.Json; import org.jclouds.json.config.GsonModule; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import com.google.inject.Guice; import com.google.inject.Injector; @Test(groups = "unit", testName = "BootstrapConfigForGroupTest") public class BootstrapConfigForGroupTest { private Json json; @BeforeClass public void setup() { Injector injector = Guice.createInjector(new GsonModule()); json = injector.getInstance(Json.class); } @Test(expectedExceptions = IllegalStateException.class) public void testWhenNoDatabagItem() throws IOException { ChefApi chefApi = createMock(ChefApi.class); Client client = createMock(Client.class); BootstrapConfigForGroup fn = new BootstrapConfigForGroup("jclouds", chefApi, json); expect(chefApi.getDatabagItem("jclouds", "foo")).andReturn(null); replay(client, chefApi); fn.apply("foo"); verify(client, chefApi); } @Test public void testReturnsItem() throws IOException { ChefApi chefApi = createMock(ChefApi.class); Client client = createMock(Client.class); BootstrapConfigForGroup fn = new BootstrapConfigForGroup("jclouds", chefApi, json); DatabagItem databag = new DatabagItem("foo", "{\"environment\":\"development\",\"ssl_ca_file\":\"/etc/certs/chef-server.crt\"," + "\"ssl_verify_mode\": \":verify_peer\"," + "\"run_list\":[\"recipe[apache2]\",\"role[webserver]\"]," + "\"attributes\":{\"tomcat6\":{\"ssl_port\":8433}}}"); expect(chefApi.getDatabagItem("jclouds", "foo")).andReturn(databag); replay(client, chefApi); BootstrapConfig config = fn.apply("foo"); assertEquals(config.getEnvironment(), "development"); assertEquals(config.getSslCAFile(), "/etc/certs/chef-server.crt"); assertEquals(config.getSslVerifyMode(), SSLVerifyMode.PEER); assertEquals(config.getRunList().get(0), "recipe[apache2]"); assertEquals(config.getRunList().get(1), "role[webserver]"); assertEquals(config.getAttributes().toString(), "{\"tomcat6\":{\"ssl_port\":8433}}"); verify(client, chefApi); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/functions/ClientForGroupTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.functions; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; import static org.testng.Assert.assertEquals; import java.io.IOException; import java.security.PrivateKey; import org.jclouds.chef.ChefApi; import org.jclouds.chef.domain.Client; import org.testng.annotations.Test; import com.google.common.collect.ImmutableSet; @Test(groups = "unit", testName = "ClientForGroupTest") public class ClientForGroupTest { public void testWhenNoClientsInList() throws IOException { ChefApi chefApi = createMock(ChefApi.class); Client client = createMock(Client.class); PrivateKey privateKey = createMock(PrivateKey.class); ClientForGroup fn = new ClientForGroup(chefApi); expect(chefApi.listClients()).andReturn(ImmutableSet. of()); expect(chefApi.createClient("foo-client-00")).andReturn(client); expect(client.getPrivateKey()).andReturn(privateKey); replay(client); replay(chefApi); Client compare = fn.apply("foo"); assertEquals(compare.getClientname(), "foo-client-00"); assertEquals(compare.getName(), "foo-client-00"); assertEquals(compare.getPrivateKey(), privateKey); verify(client); verify(chefApi); } public void testWhenClientsInListAddsToEnd() throws IOException { ChefApi chefApi = createMock(ChefApi.class); Client client = createMock(Client.class); PrivateKey privateKey = createMock(PrivateKey.class); ClientForGroup fn = new ClientForGroup(chefApi); expect(chefApi.listClients()).andReturn( ImmutableSet. of("foo-client-00", "foo-client-01", "foo-client-02")); expect(chefApi.createClient("foo-client-03")).andReturn(client); expect(client.getPrivateKey()).andReturn(privateKey); replay(client); replay(chefApi); Client compare = fn.apply("foo"); assertEquals(compare.getClientname(), "foo-client-03"); assertEquals(compare.getName(), "foo-client-03"); assertEquals(compare.getPrivateKey(), privateKey); verify(client); verify(chefApi); } public void testWhenClientsInListReplacesMissing() throws IOException { ChefApi chefApi = createMock(ChefApi.class); Client client = createMock(Client.class); PrivateKey privateKey = createMock(PrivateKey.class); ClientForGroup fn = new ClientForGroup(chefApi); expect(chefApi.listClients()).andReturn(ImmutableSet. of("foo-client-00", "foo-client-02")); expect(chefApi.createClient("foo-client-01")).andReturn(client); expect(client.getPrivateKey()).andReturn(privateKey); replay(client); replay(chefApi); Client compare = fn.apply("foo"); assertEquals(compare.getClientname(), "foo-client-01"); assertEquals(compare.getName(), "foo-client-01"); assertEquals(compare.getPrivateKey(), privateKey); verify(client); verify(chefApi); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/functions/GroupToBootScriptTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.functions; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; import static org.jclouds.chef.config.ChefProperties.CHEF_UPDATE_GEMS; import static org.jclouds.chef.config.ChefProperties.CHEF_UPDATE_GEM_SYSTEM; import static org.jclouds.chef.config.ChefProperties.CHEF_USE_OMNIBUS; import static org.testng.Assert.assertEquals; import java.io.IOException; import java.net.URI; import java.security.PrivateKey; import org.jclouds.chef.ChefApiMetadata; import org.jclouds.chef.config.ChefBootstrapModule; import org.jclouds.chef.config.ChefParserModule; import org.jclouds.chef.config.InstallChef; import org.jclouds.chef.domain.BootstrapConfig; import org.jclouds.chef.domain.BootstrapConfig.SSLVerifyMode; import org.jclouds.chef.util.RunListBuilder; import org.jclouds.crypto.PemsTest; import org.jclouds.domain.JsonBall; import org.jclouds.json.config.GsonModule; import org.jclouds.rest.annotations.ApiVersion; import org.jclouds.scriptbuilder.domain.OsFamily; import org.jclouds.scriptbuilder.domain.ShellToken; import org.jclouds.scriptbuilder.domain.Statement; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import com.google.common.base.Charsets; import com.google.common.base.Functions; import com.google.common.base.Optional; import com.google.common.base.Suppliers; import com.google.common.cache.CacheLoader; import com.google.common.collect.ImmutableMap; import com.google.common.io.Resources; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.name.Names; @Test(groups = "unit", testName = "GroupToBootScriptTest") public class GroupToBootScriptTest { private Statement installChefGems; private Statement installChefOmnibus; private Optional validatorName; @BeforeClass public void setup() { Injector injectorGems = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION); bind(String.class).annotatedWith(Names.named(CHEF_UPDATE_GEM_SYSTEM)).toInstance("true"); bind(String.class).annotatedWith(Names.named(CHEF_UPDATE_GEMS)).toInstance("true"); bind(String.class).annotatedWith(Names.named(CHEF_USE_OMNIBUS)).toInstance("false"); } }, new ChefParserModule(), new GsonModule(), new ChefBootstrapModule()); Injector injectorOmnibus = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION); bind(String.class).annotatedWith(Names.named(CHEF_UPDATE_GEM_SYSTEM)).toInstance("true"); bind(String.class).annotatedWith(Names.named(CHEF_UPDATE_GEMS)).toInstance("true"); bind(String.class).annotatedWith(Names.named(CHEF_USE_OMNIBUS)).toInstance("true"); } }, new ChefParserModule(), new GsonModule(), new ChefBootstrapModule()); installChefGems = injectorGems.getInstance(Key.get(Statement.class, InstallChef.class)); installChefOmnibus = injectorOmnibus.getInstance(Key.get(Statement.class, InstallChef.class)); validatorName = Optional. of("chef-validator"); } @Test(expectedExceptions = IllegalStateException.class) public void testMustHaveValidatorName() { Optional validatorCredential = Optional.of(createMock(PrivateKey.class)); GroupToBootScript fn = new GroupToBootScript(Suppliers.ofInstance(URI.create("http://localhost:4000")), CacheLoader.from(Functions.forMap(ImmutableMap.of("foo", BootstrapConfig.builder().build()))), installChefOmnibus, Optional. absent(), validatorCredential); fn.apply("foo", null); } @Test(expectedExceptions = IllegalStateException.class) public void testMustHaveValidatorCredential() { GroupToBootScript fn = new GroupToBootScript(Suppliers.ofInstance(URI.create("http://localhost:4000")), CacheLoader.from(Functions.forMap(ImmutableMap.of("foo", BootstrapConfig.builder().build()))), installChefOmnibus, validatorName, Optional. absent()); fn.apply("foo", null); } @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "Key 'foo' not present in map") public void testMustHaveRunScriptsName() { Optional validatorCredential = Optional.of(createMock(PrivateKey.class)); GroupToBootScript fn = new GroupToBootScript(Suppliers.ofInstance(URI.create("http://localhost:4000")), CacheLoader.from(Functions.forMap(ImmutableMap. of())), installChefOmnibus, validatorName, validatorCredential); fn.apply("foo", null); } @Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = "null value in entry: foo=null") public void testMustHaveRunScriptsValue() { Optional validatorCredential = Optional.of(createMock(PrivateKey.class)); GroupToBootScript fn = new GroupToBootScript(Suppliers.ofInstance(URI.create("http://localhost:4000")), CacheLoader.from(Functions.forMap(ImmutableMap.of("foo", (BootstrapConfig) null))), installChefOmnibus, validatorName, validatorCredential); fn.apply("foo", null); } public void testOneRecipe() throws IOException { Optional validatorCredential = Optional.of(createMock(PrivateKey.class)); BootstrapConfig config = BootstrapConfig.builder().attributes(new JsonBall("{\"tomcat6\":{\"ssl_port\":8433}}")) .runList(new RunListBuilder().addRecipe("apache2").addRole("webserver").build()).build(); GroupToBootScript fn = groupToBootScriptFor(config, validatorCredential, false); PrivateKey validatorKey = validatorCredential.get(); expect(validatorKey.getEncoded()).andReturn(PemsTest.PRIVATE_KEY.getBytes()); replay(validatorKey); assertEquals( fn.apply("foo", null).render(OsFamily.UNIX), exitInsteadOfReturn(OsFamily.UNIX, readContent("test_install_ruby.sh") + readContent("test_install_rubygems.sh")) + "gem install chef --no-rdoc --no-ri\n" + readContent("bootstrap.sh")); verify(validatorKey); } public void testOneRecipeAndEnvironment() throws IOException { Optional validatorCredential = Optional.of(createMock(PrivateKey.class)); BootstrapConfig config = BootstrapConfig.builder().attributes(new JsonBall("{\"tomcat6\":{\"ssl_port\":8433}}")) .environment("env").runList(new RunListBuilder().addRecipe("apache2").addRole("webserver").build()).build(); GroupToBootScript fn = groupToBootScriptFor(config, validatorCredential, false); PrivateKey validatorKey = validatorCredential.get(); expect(validatorKey.getEncoded()).andReturn(PemsTest.PRIVATE_KEY.getBytes()); replay(validatorKey); assertEquals( fn.apply("foo", null).render(OsFamily.UNIX), exitInsteadOfReturn(OsFamily.UNIX, readContent("test_install_ruby.sh") + readContent("test_install_rubygems.sh") + "gem install chef --no-rdoc --no-ri\n" + readContent("bootstrap-env.sh"))); verify(validatorKey); } public void testOneRecipeOmnibus() throws IOException { Optional validatorCredential = Optional.of(createMock(PrivateKey.class)); BootstrapConfig config = BootstrapConfig.builder().attributes(new JsonBall("{\"tomcat6\":{\"ssl_port\":8433}}")) .runList(new RunListBuilder().addRecipe("apache2").addRole("webserver").build()).build(); GroupToBootScript fn = groupToBootScriptFor(config, validatorCredential, true); PrivateKey validatorKey = validatorCredential.get(); expect(validatorKey.getEncoded()).andReturn(PemsTest.PRIVATE_KEY.getBytes()); replay(validatorKey); assertEquals(fn.apply("foo", null).render(OsFamily.UNIX), "setupPublicCurl || exit 1\ncurl -q -s -S -L --connect-timeout 10 --max-time 600 --retry 20 " + "-X GET https://www.opscode.com/chef/install.sh |(bash)\n" + readContent("bootstrap.sh")); verify(validatorKey); } public void testOneRecipeAndEnvironmentOmnibus() throws IOException { Optional validatorCredential = Optional.of(createMock(PrivateKey.class)); BootstrapConfig config = BootstrapConfig.builder().attributes(new JsonBall("{\"tomcat6\":{\"ssl_port\":8433}}")) .environment("env").runList(new RunListBuilder().addRecipe("apache2").addRole("webserver").build()).build(); GroupToBootScript fn = groupToBootScriptFor(config, validatorCredential, true); PrivateKey validatorKey = validatorCredential.get(); expect(validatorKey.getEncoded()).andReturn(PemsTest.PRIVATE_KEY.getBytes()); replay(validatorKey); assertEquals(fn.apply("foo", null).render(OsFamily.UNIX), "setupPublicCurl || exit 1\ncurl -q -s -S -L --connect-timeout 10 --max-time 600 --retry 20 " + "-X GET https://www.opscode.com/chef/install.sh |(bash)\n" + readContent("bootstrap-env.sh")); verify(validatorKey); } public void testNoAttribtues() throws IOException { Optional validatorCredential = Optional.of(createMock(PrivateKey.class)); BootstrapConfig config = BootstrapConfig.builder() .environment("env").runList(new RunListBuilder().addRecipe("apache2").addRole("webserver").build()).build(); GroupToBootScript fn = groupToBootScriptFor(config, validatorCredential, true); PrivateKey validatorKey = validatorCredential.get(); expect(validatorKey.getEncoded()).andReturn(PemsTest.PRIVATE_KEY.getBytes()); replay(validatorKey); assertEquals(fn.apply("foo", null).render(OsFamily.UNIX), "setupPublicCurl || exit 1\ncurl -q -s -S -L --connect-timeout 10 --max-time 600 --retry 20 " + "-X GET https://www.opscode.com/chef/install.sh |(bash)\n" + readContent("bootstrap-env-noattrs.sh")); verify(validatorKey); } public void testCustomNodeName() throws IOException { Optional validatorCredential = Optional.of(createMock(PrivateKey.class)); BootstrapConfig config = BootstrapConfig.builder().attributes(new JsonBall("{\"tomcat6\":{\"ssl_port\":8433}}")) .environment("env").runList(new RunListBuilder().addRecipe("apache2").addRole("webserver").build()).build(); GroupToBootScript fn = groupToBootScriptFor(config, validatorCredential, true); PrivateKey validatorKey = validatorCredential.get(); expect(validatorKey.getEncoded()).andReturn(PemsTest.PRIVATE_KEY.getBytes()); replay(validatorKey); assertEquals(fn.apply("foo", "bar").render(OsFamily.UNIX), "setupPublicCurl || exit 1\ncurl -q -s -S -L --connect-timeout 10 --max-time 600 --retry 20 " + "-X GET https://www.opscode.com/chef/install.sh |(bash)\n" + readContent("bootstrap-node-env.sh")); verify(validatorKey); } public void testCustomSecurityOptions() throws IOException { Optional validatorCredential = Optional.of(createMock(PrivateKey.class)); BootstrapConfig config = BootstrapConfig.builder().attributes(new JsonBall("{\"tomcat6\":{\"ssl_port\":8433}}")) .runList(new RunListBuilder().addRecipe("apache2").addRole("webserver").build()) .sslCAFile(readContent("chef.crt")).sslCAPath("/etc/chef").sslVerifyMode(SSLVerifyMode.PEER) .verifyApiCert(true).build(); GroupToBootScript fn = groupToBootScriptFor(config, validatorCredential, true); PrivateKey validatorKey = validatorCredential.get(); expect(validatorKey.getEncoded()).andReturn(PemsTest.PRIVATE_KEY.getBytes()); replay(validatorKey); assertEquals(fn.apply("foo", null).render(OsFamily.UNIX), "setupPublicCurl || exit 1\ncurl -q -s -S -L --connect-timeout 10 --max-time 600 --retry 20 " + "-X GET https://www.opscode.com/chef/install.sh |(bash)\n" + readContent("bootstrap-ssl.sh")); verify(validatorKey); } private static String exitInsteadOfReturn(OsFamily family, String input) { return input.replaceAll(ShellToken.RETURN.to(family), ShellToken.EXIT.to(family)); } private GroupToBootScript groupToBootScriptFor(BootstrapConfig config, Optional validatorCredential, boolean useOmnibus) { return new GroupToBootScript(Suppliers.ofInstance(URI.create("http://localhost:4000")), CacheLoader.from(Functions.forMap(ImmutableMap.of("foo", config))), useOmnibus ? installChefOmnibus : installChefGems, validatorName, validatorCredential); } private static String readContent(String resource) throws IOException { return Resources.toString(Resources.getResource(resource), Charsets.UTF_8); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/functions/ParseClientFromJsonTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.functions; import static org.testng.Assert.assertEquals; import java.io.IOException; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.security.spec.InvalidKeySpecException; import org.jclouds.chef.ChefApiMetadata; import org.jclouds.chef.config.ChefParserModule; import org.jclouds.chef.domain.Client; import org.jclouds.crypto.Crypto; import org.jclouds.crypto.Pems; import org.jclouds.encryption.internal.JCECrypto; import org.jclouds.http.HttpResponse; import org.jclouds.http.functions.ParseJson; import org.jclouds.io.ByteStreams2; import org.jclouds.io.Payloads; import org.jclouds.io.payloads.RSADecryptingPayload; import org.jclouds.io.payloads.RSAEncryptingPayload; import org.jclouds.json.config.GsonModule; import org.jclouds.rest.annotations.ApiVersion; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import com.google.common.base.Charsets; import com.google.common.io.ByteSource; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.TypeLiteral; import java.security.interfaces.RSAPrivateCrtKey; import java.security.spec.RSAPublicKeySpec; /** * Tests behavior of {@code ParseClientFromJson} */ @Test(groups = { "unit" }) public class ParseClientFromJsonTest { private static final String PRIVATE_KEY = "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEAyb2ZJJqGm0KKR+8nfQJNsSd+F9tXNMV7CfOcW6jsqs8EZgiV\nR09hD1IYOj4YqM0qJONlgyg4xRWewdSG7QTPj1lJpVAida9sXy2+kzyagZA1Am0O\nZcbqb5hoeIDgcX+eDa79s0u0DomjcfO9EKhvHLBz+zM+3QqPRkPV8nYTbfs+HjVz\nzOU6D1B0XR3+IPZZl2AnWs2d0qhnStHcDUvnRVQ0P482YwN9VgceOZtpPz0DCKEJ\n5Tx5STub8k0/zt/VAMHQafLSuQMLd2s4ZLuOZptN//uAsTmxireqd37z+8ZTdBbJ\n8LEpJ+iCXuSfm5aUh7iw6oxvToY2AL53+jK2UQIDAQABAoIBAQDA88B3i/xWn0vX\nBVxFamCYoecuNjGwXXkSyZew616A+EOCu47bh4aTurdFbYL0YFaAtaWvzlaN2eHg\nDb+HDuTefE29+WkcGk6SshPmiz5T0XOCAICWw6wSVDkHmGwS4jZvbAFm7W8nwGk9\nYhxgxFiRngswJZFopOLoF5WXs2td8guIYNslMpo7tu50iFnBHwKO2ZsPAk8t9nnS\nxlDavKruymEmqHCr3+dtio5eaenJcp3fjoXBQOKUk3ipII29XRB8NqeCVV/7Kxwq\nckqOBEbRwBclckyIbD+RiAgKvOelORjEiE9R42vuqvxRA6k9kd9o7utlX0AUtpEn\n3gZc6LepAoGBAP9ael5Y75+sK2JJUNOOhO8ae45cdsilp2yI0X+UBaSuQs2+dyPp\nkpEHAxd4pmmSvn/8c9TlEZhr+qYbABXVPlDncxpIuw2Ajbk7s/S4XaSKsRqpXL57\nzj/QOqLkRk8+OVV9q6lMeQNqLtEj1u6JPviX70Ro+FQtRttNOYbfdP/fAoGBAMpA\nXjR5woV5sUb+REg9vEuYo8RSyOarxqKFCIXVUNsLOx+22+AK4+CQpbueWN7jotrl\nYD6uT6svWi3AAC7kiY0UI/fjVPRCUi8tVoQUE0TaU5VLITaYOB+W/bBaDE4M9560\n1NuDWO90baA5dfU44iuzva02rGJXK9+nS3o8nk/PAoGBALOL6djnDe4mwAaG6Jco\ncd4xr8jkyPzCRZuyBCSBbwphIUXLc7hDprPky064ncJD1UDmwIdkXd/fpMkg2QmA\n/CUk6LEFjMisqHojOaCL9gQZJPhLN5QUN2x1PJWGjs1vQh8Tkx0iUUCOa8bQPXNR\n+34OTsW6TUna4CSZAycLfhffAoGBAIggVsefBCvuQkF0NeUhmDCRZfhnd8y55RHR\n1HCvqKIlpv+rhcX/zmyBLuteopYyRJRsOiE2FW00i8+rIPRu4Z3Q5nybx7w3PzV9\noHN5R5baE9OyI4KpZWztpYYitZF67NcnAvVULHHOvVJQGnKYfLHJYmrJF7GA1ojM\nAuMdFbjFAoGAPxUhxwFy8gaqBahKUEZn4F81HFP5ihGhkT4QL6AFPO2e+JhIGjuR\n27+85hcFqQ+HHVtFsm81b/a+R7P4UuCRgc8eCjxQMoJ1Xl4n7VbjPbHMnIN0Ryvd\nO4ZpWDWYnCO021JTOUUOJ4J/y0416Bvkw0z59y7sNX7wDBBHHbK/XCc=\n-----END RSA PRIVATE KEY-----\n"; private static final String CERTIFICATE = "-----BEGIN CERTIFICATE-----\nMIIClzCCAgCgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBnjELMAkGA1UEBhMCVVMx\nEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFjAUBgNVBAoM\nDU9wc2NvZGUsIEluYy4xHDAaBgNVBAsME0NlcnRpZmljYXRlIFNlcnZpY2UxMjAw\nBgNVBAMMKW9wc2NvZGUuY29tL2VtYWlsQWRkcmVzcz1hdXRoQG9wc2NvZGUuY29t\nMB4XDTEwMDczMDIwNDEzMFoXDTIwMDcyNzIwNDEzMFowADCCASIwDQYJKoZIhvcN\nAQEBBQADggEPADCCAQoCggEBAMm9mSSahptCikfvJ30CTbEnfhfbVzTFewnznFuo\n7KrPBGYIlUdPYQ9SGDo+GKjNKiTjZYMoOMUVnsHUhu0Ez49ZSaVQInWvbF8tvpM8\nmoGQNQJtDmXG6m+YaHiA4HF/ng2u/bNLtA6Jo3HzvRCobxywc/szPt0Kj0ZD1fJ2\nE237Ph41c8zlOg9QdF0d/iD2WZdgJ1rNndKoZ0rR3A1L50VUND+PNmMDfVYHHjmb\naT89AwihCeU8eUk7m/JNP87f1QDB0Gny0rkDC3drOGS7jmabTf/7gLE5sYq3qnd+\n8/vGU3QWyfCxKSfogl7kn5uWlIe4sOqMb06GNgC+d/oytlECAwEAATANBgkqhkiG\n9w0BAQUFAAOBgQBftzSZxstWw60GqRTDNN/F2GnrdtnKBoXzHww3r6jtGEylYq20\n5KfKpEx+sPX0gyZuYJiXC2CkEjImAluWKcdN9ZF6VD541sheAjbiaU7q7ZsztTxF\nWUH2tCvHeDXYKPKek3QzL7bYpUhLnCN/XxEv6ibeMDwtI7f5qpk2Aspzcw==\n-----END CERTIFICATE-----\n"; private ParseJson handler; private Crypto crypto; private PrivateKey privateKey; private X509Certificate certificate; private PublicKey publicKey; @BeforeTest protected void setUpInjector() throws IOException, CertificateException, InvalidKeySpecException, NoSuchAlgorithmException { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION); } }, new ChefParserModule(), new GsonModule()); handler = injector.getInstance(Key.get(new TypeLiteral>() { })); crypto = injector.getInstance(Crypto.class); certificate = Pems.x509Certificate(ByteSource.wrap(CERTIFICATE.getBytes(Charsets.UTF_8)), null); privateKey = crypto.rsaKeyFactory().generatePrivate(Pems.privateKeySpec(ByteSource.wrap(PRIVATE_KEY.getBytes(Charsets.UTF_8)))); RSAPrivateCrtKey privk = (RSAPrivateCrtKey)privateKey; RSAPublicKeySpec publicKeySpec = new java.security.spec.RSAPublicKeySpec(privk.getModulus(), privk.getPublicExponent()); publicKey = crypto.rsaKeyFactory().generatePublic(publicKeySpec); } public void testClientWithPubKey() throws IOException, CertificateException, NoSuchAlgorithmException { Client user = Client.builder().certificate(certificate).orgname("jclouds").clientname("adriancole-jcloudstest") .name("adriancole-jcloudstest").isValidator(false).privateKey(privateKey).publicKey(publicKey).build(); assertEquals( handler.apply(HttpResponse.builder().statusCode(200).message("ok") .payload(ParseClientFromJsonTest.class.getResourceAsStream("/client.json")).build()), user); } public void testClientWithoutPubKey() throws IOException, CertificateException, NoSuchAlgorithmException { Client user = Client.builder().certificate(certificate).orgname("jclouds").clientname("adriancole-jcloudstest") .name("adriancole-jcloudstest").isValidator(false).privateKey(privateKey).build(); assertEquals( handler.apply(HttpResponse.builder().statusCode(200).message("ok") .payload(ParseClientFromJsonTest.class.getResourceAsStream("/client-no-pub-key.json")).build()), user); } @SuppressWarnings("resource") public void testEncryptionWithClientPriv() throws IOException, CertificateException, NoSuchAlgorithmException { Client user = Client.builder().certificate(certificate).orgname("jclouds").clientname("adriancole-jcloudstest") .name("adriancole-jcloudstest").isValidator(false).privateKey(privateKey).publicKey(publicKey).build(); byte[] encrypted = ByteStreams2.toByteArrayAndClose(new RSAEncryptingPayload(new JCECrypto(), Payloads.newPayload("fooya"), user .getCertificate().getPublicKey()).openStream()); assertEquals( ByteStreams2.toByteArrayAndClose(new RSADecryptingPayload(new JCECrypto(), Payloads.newPayload(encrypted), user.getPrivateKey()).openStream()), "fooya".getBytes()); assertEquals( handler.apply(HttpResponse.builder().statusCode(200).message("ok") .payload(ParseClientFromJsonTest.class.getResourceAsStream("/client.json")).build()), user); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionFromJsonTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.functions; import static org.testng.Assert.assertEquals; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import org.jclouds.chef.ChefApiMetadata; import org.jclouds.chef.config.ChefParserModule; import org.jclouds.chef.domain.CookbookDefinition; import org.jclouds.http.HttpResponse; import org.jclouds.json.config.GsonModule; import org.jclouds.rest.annotations.ApiVersion; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; @Test(groups = { "unit" }, singleThreaded = true) public class ParseCookbookDefinitionFromJsonTest { private ParseCookbookDefinitionFromJson handler; @BeforeTest protected void setUpInjector() throws IOException { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION); } }, new ChefParserModule(), new GsonModule()); handler = injector.getInstance(ParseCookbookDefinitionFromJson.class); } public void testCookbokDefinitionParsing() throws URISyntaxException { CookbookDefinition.Version v510 = CookbookDefinition.Version.builder() .url(new URI("http://localhost:4000/cookbooks/apache2/5.1.0")).version("5.1.0").build(); CookbookDefinition.Version v420 = CookbookDefinition.Version.builder() .url(new URI("http://localhost:4000/cookbooks/apache2/4.2.0")).version("4.2.0").build(); CookbookDefinition definition = CookbookDefinition.builder() .name("apache2").url(new URI("http://localhost:4000/cookbooks/apache2")).version(v510).version(v420).build(); assertEquals(handler.apply(HttpResponse .builder() .statusCode(200) .message("ok") .payload( "{" + "\"apache2\" => {" + "\"url\" => \"http://localhost:4000/cookbooks/apache2\"," + "\"versions\" => [" + "{\"url\" => \"http://localhost:4000/cookbooks/apache2/5.1.0\"," + "\"version\" => \"5.1.0\"}," + "{\"url\" => \"http://localhost:4000/cookbooks/apache2/4.2.0\"," + "\"version\" => \"4.2.0\"}" + "]" + "}" + "}").build()), definition); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookDefinitionListFromJsonTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.functions; import static org.testng.Assert.assertEquals; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import org.jclouds.chef.ChefApiMetadata; import org.jclouds.chef.config.ChefParserModule; import org.jclouds.chef.domain.CookbookDefinition; import org.jclouds.http.HttpResponse; import org.jclouds.json.config.GsonModule; import org.jclouds.rest.annotations.ApiVersion; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import com.google.common.collect.ImmutableSet; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; @Test(groups = {"unit"}, singleThreaded = true) public class ParseCookbookDefinitionListFromJsonTest { private ParseCookbookDefinitionListFromJson handler; @BeforeTest protected void setUpInjector() throws IOException { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION); } }, new ChefParserModule(), new GsonModule()); handler = injector.getInstance(ParseCookbookDefinitionListFromJson.class); } public void testCookbokDefinitionListParsing() throws URISyntaxException { CookbookDefinition.Version v510 = CookbookDefinition.Version.builder() .url(new URI("http://localhost:4000/cookbooks/apache2/5.1.0")).version("5.1.0").build(); CookbookDefinition.Version v420 = CookbookDefinition.Version.builder() .url(new URI("http://localhost:4000/cookbooks/apache2/4.2.0")).version("4.2.0").build(); CookbookDefinition apache2 = CookbookDefinition.builder() .name("apache2").url(new URI("http://localhost:4000/cookbooks/apache2")).version(v510).version(v420).build(); CookbookDefinition.Version v100 = CookbookDefinition.Version.builder() .url(new URI("http://localhost:4000/cookbooks/nginx/1.0.0")).version("1.0.0").build(); CookbookDefinition.Version v030 = CookbookDefinition.Version.builder() .url(new URI("http://localhost:4000/cookbooks/nginx/0.3.0")).version("0.3.0").build(); CookbookDefinition nginx = CookbookDefinition.builder() .name("nginx").url(new URI("http://localhost:4000/cookbooks/nginx")).version(v100).version(v030).build(); assertEquals(handler.apply(HttpResponse .builder() .statusCode(200) .message("ok") .payload( "{" + "\"apache2\" => {" + "\"url\" => \"http://localhost:4000/cookbooks/apache2\"," + "\"versions\" => [" + "{\"url\" => \"http://localhost:4000/cookbooks/apache2/5.1.0\"," + "\"version\" => \"5.1.0\"}," + "{\"url\" => \"http://localhost:4000/cookbooks/apache2/4.2.0\"," + "\"version\" => \"4.2.0\"}" + "]" + "}," + "\"nginx\" => {" + "\"url\" => \"http://localhost:4000/cookbooks/nginx\"," + "\"versions\" => [" + "{\"url\" => \"http://localhost:4000/cookbooks/nginx/1.0.0\"," + "\"version\" => \"1.0.0\"}," + "{\"url\" => \"http://localhost:4000/cookbooks/nginx/0.3.0\"," + "\"version\" => \"0.3.0\"}" + "]}" + "}").build()), ImmutableSet.of(apache2, nginx)); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookNamesFromJsonTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.functions; import static org.testng.Assert.assertEquals; import java.io.IOException; import org.jclouds.chef.ChefApiMetadata; import org.jclouds.chef.config.ChefParserModule; import org.jclouds.http.HttpResponse; import org.jclouds.json.config.GsonModule; import org.jclouds.rest.annotations.ApiVersion; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import com.google.common.collect.ImmutableSet; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; /** * Tests behavior of {@code ParseCookbookNamesFromJson}. */ @Test(groups = { "unit" }, singleThreaded = true) public class ParseCookbookNamesFromJsonTest { private ParseCookbookNamesFromJson handler; @BeforeTest protected void setUpInjector() throws IOException { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION); } }, new ChefParserModule(), new GsonModule()); handler = injector.getInstance(ParseCookbookNamesFromJson.class); } public void testParse010Response() { assertEquals(handler.apply(HttpResponse .builder() .statusCode(200) .message("ok") .payload( "{" + "\"apache2\" => {" + "\"url\" => \"http://localhost:4000/cookbooks/apache2\"," + "\"versions\" => [" + "{\"url\" => \"http://localhost:4000/cookbooks/apache2/5.1.0\"," + "\"version\" => \"5.1.0\"}," + "{\"url\" => \"http://localhost:4000/cookbooks/apache2/4.2.0\"," + "\"version\" => \"4.2.0\"}" + "]" + "}," + "\"nginx\" => {" + "\"url\" => \"http://localhost:4000/cookbooks/nginx\"," + "\"versions\" => [" + "{\"url\" => \"http://localhost:4000/cookbooks/nginx/1.0.0\"," + "\"version\" => \"1.0.0\"}," + "{\"url\" => \"http://localhost:4000/cookbooks/nginx/0.3.0\"," + "\"version\" => \"0.3.0\"}" + "]" + "}" + "}").build()), ImmutableSet.of("apache2", "nginx")); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionFromJsonTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.functions; import static com.google.common.io.BaseEncoding.base16; import static org.testng.Assert.assertEquals; import java.io.IOException; import java.net.URI; import org.jclouds.chef.ChefApiMetadata; import org.jclouds.chef.config.ChefParserModule; import org.jclouds.chef.domain.CookbookVersion; import org.jclouds.chef.domain.Grouping; import org.jclouds.chef.domain.Metadata; import org.jclouds.chef.domain.Resource; import org.jclouds.http.HttpResponse; import org.jclouds.http.functions.ParseJson; import org.jclouds.json.Json; import org.jclouds.json.config.GsonModule; import org.jclouds.rest.annotations.ApiVersion; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.TypeLiteral; /** * Tests behavior of {@code ParseCookbookVersionFromJson} */ @Test(groups = { "unit" }, singleThreaded = true) public class ParseCookbookVersionFromJsonTest { private ParseJson handler; private Injector injector; private Json json; @BeforeTest protected void setUpInjector() throws IOException { injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION); } }, new ChefParserModule(), new GsonModule()); json = injector.getInstance(Json.class); handler = injector.getInstance(Key.get(new TypeLiteral>() { })); } public void testBrew() throws IOException { CookbookVersion cookbook = handler.apply(HttpResponse.builder().statusCode(200).message("ok") .payload(ParseCookbookVersionFromJsonTest.class.getResourceAsStream("/brew-cookbook.json")).build()); assertEquals(cookbook, handler.apply(HttpResponse.builder().statusCode(200).message("ok").payload(json.toJson(cookbook)).build())); } public void testTomcat() { CookbookVersion cookbook = handler.apply(HttpResponse.builder().statusCode(200).message("ok") .payload(ParseCookbookVersionFromJsonTest.class.getResourceAsStream("/tomcat-cookbook.json")).build()); assertEquals(cookbook, handler.apply(HttpResponse.builder().statusCode(200).message("ok").payload(json.toJson(cookbook)).build())); } public void testMysql() throws IOException { CookbookVersion cookbook = handler.apply(HttpResponse.builder().statusCode(200).message("ok") .payload(ParseCookbookVersionFromJsonTest.class.getResourceAsStream("/mysql-cookbook.json")).build()); assertEquals(cookbook, handler.apply(HttpResponse.builder().statusCode(200).message("ok").payload(json.toJson(cookbook)).build())); } public void testApache() { CookbookVersion fromJson = handler.apply(HttpResponse.builder().statusCode(200).message("ok") .payload(ParseCookbookVersionFromJsonTest.class.getResourceAsStream("/apache-chef-demo-cookbook.json")) .build()); CookbookVersion expected = CookbookVersion .builder("apache-chef-demo", "0.0.0") .metadata(Metadata.builder() // .license("Apache v2.0") // .maintainer("Your Name") // .maintainerEmail("youremail@example.com") // .description("A fabulous new cookbook") // .version("0.0.0") // .name("apache-chef-demo") // .longDescription("") // .grouping("one", Grouping.builder().title("One title").description("One description").build()) // .grouping("two", Grouping.builder().title("Two title").description("Two description").build()) // .build()) .rootFile( Resource .builder() .name("README") .path("README") .checksum(base16().lowerCase().decode("11637f98942eafbf49c71b7f2f048b78")) .url(URI .create("https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-11637f98942eafbf49c71b7f2f048b78?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277766181&Signature=zgpNl6wSxjTNovqZu2nJq0JztU8%3D")) // .build()) .rootFile( Resource .builder() .name("Rakefile") .path("Rakefile") .checksum(base16().lowerCase().decode("ebcf925a1651b4e04b9cd8aac2bc54eb")) .url(URI .create("https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-ebcf925a1651b4e04b9cd8aac2bc54eb?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277766181&Signature=EFzzDSKKytTl7b%2FxrCeNLh05zj4%3D")) .build()) // .build(); assertEquals(fromJson, expected); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/functions/ParseCookbookVersionsFromJsonTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.functions; import static org.testng.Assert.assertEquals; import java.io.IOException; import org.jclouds.chef.ChefApiMetadata; import org.jclouds.chef.config.ChefParserModule; import org.jclouds.http.HttpResponse; import org.jclouds.json.config.GsonModule; import org.jclouds.rest.annotations.ApiVersion; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import com.google.common.collect.ImmutableSet; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; /** * Tests behavior of {@code ParseCookbookVersionsFromJson} */ @Test(groups = { "unit" }, singleThreaded = true) public class ParseCookbookVersionsFromJsonTest { private ParseCookbookVersionsFromJson handler; @BeforeTest protected void setUpInjector() throws IOException { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION); } }, new ChefParserModule(), new GsonModule()); handler = injector.getInstance(ParseCookbookVersionsFromJson.class); } public void testRegex() { assertEquals(handler.apply(HttpResponse .builder() .statusCode(200) .message("ok") .payload( "{" + "\"apache2\" => {" + "\"url\" => \"http://localhost:4000/cookbooks/apache2\"," + "\"versions\" => [" + "{\"url\" => \"http://localhost:4000/cookbooks/apache2/5.1.0\"," + "\"version\" => \"5.1.0\"}," + "{\"url\" => \"http://localhost:4000/cookbooks/apache2/4.2.0\"," + "\"version\" => \"4.2.0\"}" + "]" + "}" + "}").build()), ImmutableSet.of("5.1.0", "4.2.0")); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/functions/ParseDataBagItemFromJsonTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.functions; import static org.testng.Assert.assertEquals; import java.io.IOException; import org.jclouds.chef.ChefApiMetadata; import org.jclouds.chef.config.ChefParserModule; import org.jclouds.chef.domain.DatabagItem; import org.jclouds.http.HttpResponse; import org.jclouds.http.functions.ParseJson; import org.jclouds.json.Json; import org.jclouds.json.config.GsonModule; import org.jclouds.rest.annotations.ApiVersion; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.TypeLiteral; @Test(groups = { "unit" }) public class ParseDataBagItemFromJsonTest { private ParseJson handler; private Json mapper; @BeforeTest protected void setUpInjector() throws IOException { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION); } }, new ChefParserModule(), new GsonModule()); handler = injector.getInstance(Key.get(new TypeLiteral>() { })); mapper = injector.getInstance(Json.class); } public void test1() { String json = "{\"my_key\":\"my_data\",\"id\":\"item1\"}"; DatabagItem item = new DatabagItem("item1", json); assertEquals(handler.apply(HttpResponse.builder().statusCode(200).message("ok").payload(json).build()), item); assertEquals(mapper.toJson(item), json); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/functions/ParseErrorFromJsonOrReturnBodyTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.functions; import static org.testng.Assert.assertEquals; import java.io.InputStream; import java.net.UnknownHostException; import org.jclouds.http.HttpResponse; import org.jclouds.http.functions.ReturnStringIf2xx; import org.jclouds.util.Strings2; import org.testng.annotations.Test; @Test(groups = { "unit" }) public class ParseErrorFromJsonOrReturnBodyTest { @Test public void testApplyInputStreamDetails() throws UnknownHostException { InputStream is = Strings2 .toInputStream("{\"error\":[\"invalid tarball: tarball root must contain java-bytearray\"]}"); ParseErrorFromJsonOrReturnBody parser = new ParseErrorFromJsonOrReturnBody(new ReturnStringIf2xx()); String response = parser.apply(HttpResponse.builder().statusCode(200).message("ok").payload(is).build()); assertEquals(response, "invalid tarball: tarball root must contain java-bytearray"); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/functions/ParseKeySetFromJsonTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.functions; import static org.testng.Assert.assertEquals; import java.io.IOException; import org.jclouds.chef.ChefApiMetadata; import org.jclouds.chef.config.ChefParserModule; import org.jclouds.http.HttpResponse; import org.jclouds.json.config.GsonModule; import org.jclouds.rest.annotations.ApiVersion; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import com.google.common.collect.ImmutableSet; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; /** * Tests behavior of {@code ParseKeySetFromJson} */ @Test(groups = { "unit" }, singleThreaded = true) public class ParseKeySetFromJsonTest { private ParseKeySetFromJson handler; @BeforeTest protected void setUpInjector() throws IOException { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION); } }, new ChefParserModule(), new GsonModule()); handler = injector.getInstance(ParseKeySetFromJson.class); } public void testRegex() { assertEquals( handler.apply(HttpResponse .builder() .statusCode(200) .message("ok") .payload( "{\n\"opscode-validator\": \"https://api.opscode.com/...\", \"pimp-validator\": \"https://api.opscode.com/...\"}") .build()), ImmutableSet.of("opscode-validator", "pimp-validator")); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/functions/ParseNodeFromJsonTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.functions; import static org.testng.Assert.assertEquals; import java.io.IOException; import org.jclouds.chef.ChefApiMetadata; import org.jclouds.chef.config.ChefParserModule; import org.jclouds.chef.domain.Node; import org.jclouds.domain.JsonBall; import org.jclouds.http.HttpResponse; import org.jclouds.http.functions.ParseJson; import org.jclouds.json.config.GsonModule; import org.jclouds.rest.annotations.ApiVersion; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.TypeLiteral; /** * Tests behavior of {@code ParseNodeFromJson} */ @Test(groups = { "unit" }, singleThreaded = true) public class ParseNodeFromJsonTest { private ParseJson handler; @BeforeTest protected void setUpInjector() throws IOException { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION); } }, new ChefParserModule(), new GsonModule()); handler = injector.getInstance(Key.get(new TypeLiteral>() { })); } public void test() { Node node = Node.builder() // .name("adrian-jcloudstest") // .normalAttribute("tomcat6", new JsonBall("{\"ssl_port\":8433}")) // .runListElement("recipe[java]") // .environment("prod") // .build(); assertEquals( handler.apply(HttpResponse.builder().statusCode(200).message("ok") .payload(ParseCookbookVersionFromJsonTest.class.getResourceAsStream("/node.json")).build()), node); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/functions/ParseSandboxFromJsonTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.functions; import static org.testng.Assert.assertEquals; import java.io.IOException; import org.jclouds.chef.ChefApiMetadata; import org.jclouds.chef.config.ChefParserModule; import org.jclouds.chef.domain.Sandbox; import org.jclouds.date.DateService; import org.jclouds.http.HttpResponse; import org.jclouds.http.functions.ParseJson; import org.jclouds.json.config.GsonModule; import org.jclouds.rest.annotations.ApiVersion; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.TypeLiteral; /** * Tests behavior of {@code ParseSandboxFromJson} */ @Test(groups = { "unit" }, singleThreaded = true) public class ParseSandboxFromJsonTest { private ParseJson handler; private DateService dateService; @BeforeTest protected void setUpInjector() throws IOException { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION); } }, new ChefParserModule(), new GsonModule()); handler = injector.getInstance(Key.get(new TypeLiteral>() { })); dateService = injector.getInstance(DateService.class); } public void test() { assertEquals( handler.apply(HttpResponse.builder().statusCode(200).message("ok") .payload(ParseSandboxFromJsonTest.class.getResourceAsStream("/sandbox.json")).build()), Sandbox.builder().rev("1-8c27b0ea4c2b7aaedbb44cfbdfcc11b2").isCompleted(false) .createTime(dateService.iso8601SecondsDateParse("2010-07-07T03:36:00+00:00")) .name("f9d6d9b72bae465890aae87969f98a9c").guid("f9d6d9b72bae465890aae87969f98a9c").build()); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/functions/ParseSearchDataBagItemFromJsonTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.functions; import static org.testng.Assert.assertEquals; import java.io.IOException; import org.jclouds.chef.ChefApiMetadata; import org.jclouds.chef.config.ChefParserModule; import org.jclouds.chef.domain.DatabagItem; import org.jclouds.chef.domain.SearchResult; import org.jclouds.http.HttpResponse; import org.jclouds.json.config.GsonModule; import org.jclouds.rest.annotations.ApiVersion; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; @Test(groups = { "unit" }) public class ParseSearchDataBagItemFromJsonTest { private ParseSearchDatabagFromJson handler; @BeforeTest protected void setUpInjector() throws IOException { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION); } }, new ChefParserModule(), new GsonModule()); handler = injector.getInstance(ParseSearchDatabagFromJson.class); } public void test1() { String itemJson = "{\"my_key\":\"my_data\"}"; String searchJson = "{\"rows\":[{\"raw_data\": {\"id\":\"item1\",\"my_key\":\"my_data\"}}]}"; DatabagItem item = new DatabagItem("item1", itemJson); SearchResult result = handler.apply(HttpResponse.builder().statusCode(200).message("ok") .payload(searchJson).build()); assertEquals(result.size(), 1); assertEquals(result.iterator().next(), item); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/functions/ParseUploadSandboxFromJsonTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.functions; import static com.google.common.io.BaseEncoding.base16; import static com.google.common.primitives.Bytes.asList; import static org.testng.Assert.assertEquals; import java.io.IOException; import java.net.URI; import org.jclouds.chef.ChefApiMetadata; import org.jclouds.chef.config.ChefParserModule; import org.jclouds.chef.domain.ChecksumStatus; import org.jclouds.chef.domain.UploadSandbox; import org.jclouds.http.HttpResponse; import org.jclouds.http.functions.ParseJson; import org.jclouds.json.config.GsonModule; import org.jclouds.rest.annotations.ApiVersion; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.TypeLiteral; /** * Tests behavior of {@code ParseUploadSiteFromJson} */ @Test(groups = { "unit" }, singleThreaded = true) public class ParseUploadSandboxFromJsonTest { private ParseJson handler; private Injector injector; @BeforeTest protected void setUpInjector() throws IOException { injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION); } }, new ChefParserModule(), new GsonModule()); handler = injector.getInstance(Key.get(new TypeLiteral>() { })); } public void test() { assertEquals( handler.apply(HttpResponse.builder().statusCode(200).message("ok") .payload(ParseUploadSandboxFromJsonTest.class.getResourceAsStream("/upload-site.json")).build()), UploadSandbox .builder() .uri(URI .create("https://api.opscode.com/organizations/jclouds/sandboxes/d454f71e2a5f400c808d0c5d04c2c88c")) .checksum( asList(base16().lowerCase().decode("0c5ecd7788cf4f6c7de2a57193897a6c")), ChecksumStatus .builder() .url(URI .create("https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/sandbox-d454f71e2a5f400c808d0c5d04c2c88c/checksum-0c5ecd7788cf4f6c7de2a57193897a6c?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277344702&Signature=FtKyqvYEjhhEKmRY%2B0M8aGPMM7g%3D")) .needsUpload(true).build()) .checksum(asList(base16().lowerCase().decode("0189e76ccc476701d6b374e5a1a27347")), ChecksumStatus.builder().build()) .checksum(asList(base16().lowerCase().decode("1dda05ed139664f1f89b9dec482b77c0")), ChecksumStatus.builder().build()).sandboxId("d454f71e2a5f400c808d0c5d04c2c88c").build() ); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/functions/UriForResourceTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.functions; import static org.testng.Assert.assertEquals; import java.net.URI; import org.jclouds.chef.domain.Resource; import org.testng.annotations.Test; import com.google.common.base.Function; /** * Tests behavior of {@code UriForResource} */ @Test(groups = { "unit" }) public class UriForResourceTest { @Test(expectedExceptions = NullPointerException.class) public void testWithNullInput() { Function function = new UriForResource(); function.apply(null); } @Test(expectedExceptions = IllegalArgumentException.class) public void testWithInvalidInput() { Function function = new UriForResource(); function.apply(new Object()); } @Test public void testWithValidResource() { Function function = new UriForResource(); Resource res = Resource.builder().name("test").url(URI.create("http://foo/bar")).build(); URI result = function.apply(res); assertEquals(res.getUrl().toString(), result.toString()); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/handlers/ChefApiErrorRetryHandlerTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.handlers; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; import org.jclouds.http.HttpCommand; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; import org.jclouds.http.handlers.BackoffLimitedRetryHandler; import org.testng.annotations.Test; /** * Tests behavior of {@code ChefClientErrorRetryHandler} */ @Test(groups = { "unit" }) public class ChefApiErrorRetryHandlerTest { @Test public void test401DoesNotRetry() { HttpCommand command = createMock(HttpCommand.class); HttpResponse response = createMock(HttpResponse.class); BackoffLimitedRetryHandler retry = createMock(BackoffLimitedRetryHandler.class); expect(command.getFailureCount()).andReturn(0); expect(response.getStatusCode()).andReturn(401).atLeastOnce(); replay(response); replay(retry); replay(command); ChefApiErrorRetryHandler handler = new ChefApiErrorRetryHandler(retry); assert !handler.shouldRetryRequest(command, response); verify(retry); verify(command); verify(response); } @Test public void test400DoesNotRetry() { HttpCommand command = createMock(HttpCommand.class); HttpResponse response = createMock(HttpResponse.class); BackoffLimitedRetryHandler retry = createMock(BackoffLimitedRetryHandler.class); expect(command.getFailureCount()).andReturn(0); expect(response.getStatusCode()).andReturn(401).atLeastOnce(); replay(response); replay(retry); replay(command); ChefApiErrorRetryHandler handler = new ChefApiErrorRetryHandler(retry); assert !handler.shouldRetryRequest(command, response); verify(retry); verify(command); verify(response); } @Test public void testRetryOn400PutSandbox() { HttpCommand command = createMock(HttpCommand.class); BackoffLimitedRetryHandler retry = createMock(BackoffLimitedRetryHandler.class); HttpRequest request = HttpRequest.builder().method("PUT") .endpoint("https://api.opscode.com/organizations/jclouds/sandboxes/bfd68d4052f44053b2e593a33b5e1cd5") .build(); HttpResponse response = HttpResponse .builder() .statusCode(400) .message("400 Bad Request") .payload( "{\"error\":[\"Cannot update sandbox bfd68d4052f44053b2e593a33b5e1cd5: checksum 9b7c23369f4b576451216c39f214af6c was not uploaded\"]}") .build(); expect(command.getFailureCount()).andReturn(0); expect(command.getCurrentRequest()).andReturn(request).atLeastOnce(); expect(retry.shouldRetryRequest(command, response)).andReturn(true); replay(retry); replay(command); ChefApiErrorRetryHandler handler = new ChefApiErrorRetryHandler(retry); assert handler.shouldRetryRequest(command, response); verify(retry); verify(command); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/internal/BaseChefLiveTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.internal; import java.io.File; import java.io.IOException; import java.util.Properties; import org.jclouds.apis.BaseApiLiveTest; import org.jclouds.chef.ChefApi; import org.jclouds.chef.ChefService; import org.jclouds.json.Json; import org.testng.annotations.Test; import com.google.common.base.Charsets; import com.google.common.base.Throwables; import com.google.common.io.Files; import com.google.inject.Injector; import com.google.inject.Module; @Test(groups = "live") public abstract class BaseChefLiveTest extends BaseApiLiveTest { protected Injector injector; protected ChefService chefService; protected Json json; protected BaseChefLiveTest() { provider = "chef"; } /** * the credential is a path to the pem file. */ @Override protected Properties setupProperties() { Properties overrides = super.setupProperties(); credential = setCredentialFromPemFile(overrides, identity, provider + ".credential"); return overrides; } @Override protected void initialize() { super.initialize(); chefService = injector.getInstance(ChefService.class); json = injector.getInstance(Json.class); } @Override protected ChefApi create(Properties props, Iterable modules) { injector = newBuilder().modules(modules).overrides(props).buildInjector(); return injector.getInstance(ChefApi.class); } protected String setCredentialFromPemFile(Properties overrides, String identity, String key) { String val = null; String credentialFromFile = null; if (System.getProperties().containsKey("test." + key)) { val = System.getProperty("test." + key); } else { val = System.getProperty("user.home") + "/.chef/" + identity + ".pem"; } try { credentialFromFile = Files.toString(new File(val), Charsets.UTF_8); } catch (IOException e) { throw Throwables.propagate(e); } overrides.setProperty(key, credentialFromFile); return credentialFromFile; } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/internal/BaseChefServiceTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.internal; import static org.testng.Assert.assertEquals; import java.util.List; import org.jclouds.ContextBuilder; import org.jclouds.chef.ChefApiMetadata; import org.jclouds.chef.domain.BootstrapConfig; import org.jclouds.chef.filters.SignedHeaderAuthTest; import org.jclouds.chef.util.RunListBuilder; import org.jclouds.domain.JsonBall; import org.jclouds.logging.config.NullLoggingModule; import org.jclouds.rest.internal.BaseRestApiTest.MockModule; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.inject.Injector; import com.google.inject.Module; /** * Unit tests for the BaseChefService class. */ @Test(groups = "unit", testName = "BaseChefServiceTest") public class BaseChefServiceTest { private BaseChefService chefService; @BeforeClass public void setup() { Injector injector = ContextBuilder.newBuilder(new ChefApiMetadata()) .credentials(SignedHeaderAuthTest.USER_ID, SignedHeaderAuthTest.PRIVATE_KEY) .modules(ImmutableSet. of(new MockModule(), new NullLoggingModule())).buildInjector(); chefService = injector.getInstance(BaseChefService.class); } public void testBuildBootstrapConfigurationWithEmptyRunlist() { BootstrapConfig bootstrapConfig = BootstrapConfig.builder().runList(ImmutableList. of()).build(); String config = chefService.buildBootstrapConfiguration(bootstrapConfig); assertEquals(config, "{\"run_list\":[]}"); } public void testBuildBootstrapConfigurationWithRunlist() { List runlist = new RunListBuilder().addRecipe("apache2").addRole("webserver").build(); BootstrapConfig bootstrapConfig = BootstrapConfig.builder().runList(runlist).build(); String config = chefService.buildBootstrapConfiguration(bootstrapConfig); assertEquals(config, "{\"run_list\":[\"recipe[apache2]\",\"role[webserver]\"]}"); } public void testBuildBootstrapConfigurationWithRunlistAndEmptyAttributes() { List runlist = new RunListBuilder().addRecipe("apache2").addRole("webserver").build(); BootstrapConfig bootstrapConfig = BootstrapConfig.builder().runList(runlist).attributes(new JsonBall("{}")) .build(); String config = chefService.buildBootstrapConfiguration(bootstrapConfig); assertEquals(config, "{\"run_list\":[\"recipe[apache2]\",\"role[webserver]\"],\"attributes\":{}}"); } public void testBuildBootstrapConfigurationWithRunlistAndAttributes() { List runlist = new RunListBuilder().addRecipe("apache2").addRole("webserver").build(); BootstrapConfig bootstrapConfig = BootstrapConfig.builder().runList(runlist) .attributes(new JsonBall("{\"tomcat6\":{\"ssl_port\":8433}}")).build(); String config = chefService.buildBootstrapConfiguration(bootstrapConfig); assertEquals(config, "{\"run_list\":[\"recipe[apache2]\",\"role[webserver]\"],\"attributes\":{\"tomcat6\":{\"ssl_port\":8433}}}"); } public void testBuildBootstrapConfigurationWithRunlistAndAttributesAndEnvironment() { List runlist = new RunListBuilder().addRecipe("apache2").addRole("webserver").build(); BootstrapConfig bootstrapConfig = BootstrapConfig.builder().runList(runlist) .attributes(new JsonBall("{\"tomcat6\":{\"ssl_port\":8433}}")).environment("env").build(); String config = chefService.buildBootstrapConfiguration(bootstrapConfig); assertEquals(config, "{\"run_list\":[\"recipe[apache2]\",\"role[webserver]\"],\"environment\":\"env\"," + "\"attributes\":{\"tomcat6\":{\"ssl_port\":8433}}}"); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/strategy/internal/CleanupStaleNodesAndClientsImplLiveTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.strategy.internal; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; import org.jclouds.chef.internal.BaseChefLiveTest; import org.testng.annotations.Test; import com.google.common.collect.ImmutableSet; /** * Tests behavior of {@code CleanupStaleNodesAndClientsImpl} strategies */ @Test(groups = "live", testName = "CleanupStaleNodesAndClientsImplLiveTest") public class CleanupStaleNodesAndClientsImplLiveTest extends BaseChefLiveTest { private CreateNodeAndPopulateAutomaticAttributesImpl creator; private CleanupStaleNodesAndClientsImpl strategy; @Override protected void initialize() { super.initialize(); this.prefix = this.prefix + "-" + this.hashCode(); this.creator = injector.getInstance(CreateNodeAndPopulateAutomaticAttributesImpl.class); this.strategy = injector.getInstance(CleanupStaleNodesAndClientsImpl.class); } @Test public void testExecute() throws InterruptedException { try { creator.execute(prefix, ImmutableSet. of()); // http://tickets.corp.opscode.com/browse/PL-522 // assert chef.nodeExists(prefix); assertNotNull(api.getNode(prefix)); strategy.execute(prefix, 10); assertNotNull(api.getNode(prefix)); Thread.sleep(1000); strategy.execute(prefix, 1); assertNull(api.getNode(prefix)); } finally { api.deleteNode(prefix); } } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/strategy/internal/CreateNodeAndPopulateAutomaticAttributesImplLiveTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.strategy.internal; import static org.testng.Assert.assertEquals; import java.util.Set; import org.jclouds.chef.domain.Node; import org.jclouds.chef.internal.BaseChefLiveTest; import org.jclouds.ohai.config.OhaiModule.CurrentUserProvider; import org.testng.annotations.Test; import com.google.common.collect.ImmutableSet; /** * Tests behavior of {@code CreateNodeAndPopulateAutomaticAttributesImpl} * strategies */ @Test(groups = "live", testName = "CreateNodeAndPopulateAutomaticAttributesImplLiveTest") public class CreateNodeAndPopulateAutomaticAttributesImplLiveTest extends BaseChefLiveTest { private CurrentUserProvider currentUserProvider; private CreateNodeAndPopulateAutomaticAttributesImpl strategy; @Override protected void initialize() { super.initialize(); this.prefix = this.prefix + "-" + this.hashCode(); this.currentUserProvider = injector.getInstance(CurrentUserProvider.class); this.strategy = injector.getInstance(CreateNodeAndPopulateAutomaticAttributesImpl.class); } @Test public void testExecute() { Set runList = ImmutableSet.of("role[" + prefix + "]"); try { strategy.execute(prefix, runList); Node node = api.getNode(prefix); assertEquals(node.getName(), prefix); assertEquals(node.getRunList(), runList); assertEquals(node.getAutomaticAttributes().get("current_user").toString(), currentUserProvider.get().toString()); } finally { api.deleteNode(prefix); } } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/strategy/internal/CreateNodeAndPopulateAutomaticAttributesImplTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.strategy.internal; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; import java.util.Map; import org.jclouds.chef.ChefApi; import org.jclouds.chef.domain.Node; import org.jclouds.domain.JsonBall; import org.testng.annotations.Test; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; /** * Tests behavior of {@code CreateNodeAndPopulateAutomaticAttributesImpl} */ @Test(groups = "unit", testName = "CreateNodeAndPopulateAutomaticAttributesImplTest") public class CreateNodeAndPopulateAutomaticAttributesImplTest { @Test public void testWithNoRunlist() { ChefApi chef = createMock(ChefApi.class); Supplier> automaticSupplier = Suppliers.> ofInstance(ImmutableMap. of()); Node nodeWithAutomatic = Node.builder().name("name").environment("_default") .automaticAttributes(automaticSupplier.get()).build(); chef.createNode(nodeWithAutomatic); replay(chef); CreateNodeAndPopulateAutomaticAttributesImpl updater = new CreateNodeAndPopulateAutomaticAttributesImpl(chef, automaticSupplier); updater.execute("name", ImmutableSet. of()); verify(chef); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/strategy/internal/DeleteAllApisAndNodesInListImplLiveTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.strategy.internal; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; import org.jclouds.chef.internal.BaseChefLiveTest; import org.testng.annotations.Test; import com.google.common.collect.ImmutableSet; /** * Tests behavior of {@code DeleteAllApisAndNodesInListImpl} strategies */ @Test(groups = "live", testName = "DeleteAllApisAndNodesInListImplLiveTest") public class DeleteAllApisAndNodesInListImplLiveTest extends BaseChefLiveTest { private DeleteAllNodesInListImpl strategy; private CreateNodeAndPopulateAutomaticAttributesImpl creator; @Override protected void initialize() { super.initialize(); this.prefix = this.prefix + "-" + this.hashCode(); this.creator = injector.getInstance(CreateNodeAndPopulateAutomaticAttributesImpl.class); this.strategy = injector.getInstance(DeleteAllNodesInListImpl.class); } @Test public void testExecute() throws InterruptedException { try { creator.execute(prefix, ImmutableSet. of()); creator.execute(prefix + 1, ImmutableSet. of()); // http://tickets.corp.opscode.com/browse/PL-522 // assert api.nodeExists(prefix); assertNotNull(api.getNode(prefix)); assertNotNull(api.getNode(prefix + 1)); strategy.execute(ImmutableSet.of(prefix, prefix + 1)); assertNull(api.getNode(prefix)); assertNull(api.getNode(prefix + 1)); } finally { api.deleteNode(prefix); api.deleteNode(prefix + 1); } } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/strategy/internal/ListCookbookVersionsInEnvironmentImplLiveTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.strategy.internal; import static com.google.common.collect.Iterables.size; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; import java.io.File; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import org.jclouds.chef.domain.ChecksumStatus; import org.jclouds.chef.domain.CookbookVersion; import org.jclouds.chef.domain.Metadata; import org.jclouds.chef.domain.Resource; import org.jclouds.chef.domain.Sandbox; import org.jclouds.chef.domain.UploadSandbox; import org.jclouds.chef.internal.BaseChefLiveTest; import org.jclouds.io.Payloads; import org.jclouds.io.payloads.FilePayload; import org.testng.annotations.AfterClass; import org.testng.annotations.Test; import com.google.common.collect.ImmutableSet; import com.google.common.hash.Hashing; import com.google.common.io.Files; import com.google.common.primitives.Bytes; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.MoreExecutors; /** * Tests behavior of {@code ListCookbookVersionsInEnvironmentImpl} strategies */ @Test(groups = "live", testName = "ListCookbookVersionsInEnvironmentImplLiveTest") public class ListCookbookVersionsInEnvironmentImplLiveTest extends BaseChefLiveTest { public static final String PREFIX = "jcloudstest-strategy-" + System.getProperty("user.name"); private ListCookbookVersionsInEnvironmentImpl strategy; private ExecutorService testExecutorService; private ListeningExecutorService testListeningExecutorService; @Override protected void initialize() { super.initialize(); try { createCookbooksWithMultipleVersions(PREFIX); createCookbooksWithMultipleVersions(PREFIX + 1); } catch (Exception e) { fail("Could not create cookbooks", e); } this.strategy = injector.getInstance(ListCookbookVersionsInEnvironmentImpl.class); this.testExecutorService = Executors.newFixedThreadPool(5); this.testListeningExecutorService = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(5)); } @AfterClass(groups = { "integration", "live" }) @Override protected void tearDown() { api.deleteCookbook(PREFIX, "0.0.0"); api.deleteCookbook(PREFIX, "1.0.0"); api.deleteCookbook(PREFIX + 1, "0.0.0"); api.deleteCookbook(PREFIX + 1, "1.0.0"); this.testExecutorService.shutdown(); this.testListeningExecutorService.shutdown(); super.tearDown(); } @Test public void testExecute() { assertTrue(size(strategy.execute("_default")) > 0, "Expected one or more elements"); } @Test public void testExecuteConcurrentlyWithExecutorService() { assertTrue(size(strategy.execute(testExecutorService, "_default")) > 0, "Expected one or more elements"); } @Test public void testExecuteConcurrentlyWithListeningExecutorService() { assertTrue(size(strategy.execute(testListeningExecutorService, "_default")) > 0, "Expected one or more elements"); } @Test public void testExecuteWithNumVersions() { assertTrue(size(strategy.execute("_default", "2")) > 0, "Expected one or more elements"); } @Test public void testExecuteConcurrentlyWithNumVersionsAndExecutorService() { assertTrue(size(strategy.execute(testExecutorService, "_default", "2")) > 0, "Expected one or more elements"); } @Test public void testExecuteConcurrentlyWithNumVersionsAndListeningExecutorService() { assertTrue(size(strategy.execute(testListeningExecutorService, "_default", "2")) > 0, "Expected one or more elements"); } @Test public void testExecuteWithNumVersionsAll() { assertTrue(size(strategy.execute("_default", "all")) > 0, "Expected one or more elements"); } @Test public void testExecuteConcurrentlyWithNumVersionsAllAndExecutorService() { assertTrue(size(strategy.execute(testExecutorService, "_default", "all")) > 0, "Expected one or more elements"); } @Test public void testExecuteConcurrentlyWithNumVersionsAllAndListeningExecutorService() { assertTrue(size(strategy.execute(testListeningExecutorService, "_default", "all")) > 0, "Expected one or more elements"); } private FilePayload uploadContent(String fileName) throws Exception { // Define the file you want in the cookbook File file = new File(System.getProperty("user.dir"), fileName); FilePayload content = Payloads.newFilePayload(file); content.getContentMetadata().setContentType("application/x-binary"); // Get an md5 so that you can see if the server already has it or not content.getContentMetadata().setContentMD5(Files.asByteSource(file).hash(Hashing.md5()).asBytes()); // Note that java collections cannot effectively do equals or hashcodes on // byte arrays, so let's convert to a list of bytes. List md5 = Bytes.asList(content.getContentMetadata().getContentMD5()); // Request an upload site for this file UploadSandbox site = api.createUploadSandboxForChecksums(ImmutableSet.of(md5)); assertTrue(site.getChecksums().containsKey(md5), md5 + " not in " + site.getChecksums()); try { // Upload the file contents, if still not uploaded ChecksumStatus status = site.getChecksums().get(md5); if (status.needsUpload()) { api.uploadContent(status.getUrl(), content); } Sandbox sandbox = api.commitSandbox(site.getSandboxId(), true); assertTrue(sandbox.isCompleted(), "Sandbox should be completed after uploading"); } catch (RuntimeException e) { api.commitSandbox(site.getSandboxId(), false); fail("Could not upload content", e); } return content; } private void createCookbooksWithMultipleVersions(String cookbookName) throws Exception { FilePayload v0content = uploadContent("pom.xml"); FilePayload v1content = uploadContent("../../README.md"); // Create the metadata of the cookbook Metadata metadata = Metadata.builder() // .name(cookbookName) // .version("0.0.0") // .description("Jclouds test uploaded cookbook") // .maintainer("jclouds") // .maintainerEmail("someone@jclouds.org") // .license("Apache 2.0") // .build(); // Create new cookbook version CookbookVersion cookbook = CookbookVersion.builder(cookbookName, "0.0.0") // .metadata(metadata) // .rootFile(Resource.builder().fromPayload(v0content).build()) // .build(); // upload the cookbook to the remote server api.updateCookbook(cookbookName, "0.0.0", cookbook); // Create the metadata of the cookbook metadata = Metadata.builder() // .name(cookbookName) // .version("1.0.0") // .description("Jclouds test uploaded cookbook") // .maintainer("jclouds") // .maintainerEmail("someone@jclouds.org") // .license("Apache 2.0") // .build(); // Create a new cookbook version cookbook = CookbookVersion.builder(cookbookName, "1.0.0") // .metadata(metadata) // .rootFile(Resource.builder().fromPayload(v1content).build()) // .build(); // upload the cookbook to the remote server api.updateCookbook(cookbookName, "1.0.0", cookbook); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/strategy/internal/ListNodesImplLiveTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.strategy.internal; import static com.google.common.collect.Iterables.size; import static org.testng.Assert.assertTrue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import org.jclouds.chef.internal.BaseChefLiveTest; import org.testng.annotations.AfterClass; import org.testng.annotations.Test; import com.google.common.collect.ImmutableSet; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.MoreExecutors; /** * Tests behavior of {@code ListNodesImpl} strategies */ @Test(groups = "live", testName = "ListNodesImplLiveTest") public class ListNodesImplLiveTest extends BaseChefLiveTest { private ListNodesImpl strategy; private CreateNodeAndPopulateAutomaticAttributesImpl creator; private ExecutorService testExecutorService; private ListeningExecutorService testListeningExecutorService; @Override protected void initialize() { super.initialize(); this.creator = injector.getInstance(CreateNodeAndPopulateAutomaticAttributesImpl.class); this.strategy = injector.getInstance(ListNodesImpl.class); creator.execute(prefix, ImmutableSet. of()); creator.execute(prefix + 1, ImmutableSet. of()); this.testExecutorService = Executors.newFixedThreadPool(5); this.testListeningExecutorService = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(5)); } @AfterClass(groups = { "integration", "live" }) @Override protected void tearDown() { api.deleteNode(prefix); api.deleteNode(prefix + 1); this.testExecutorService.shutdown(); this.testListeningExecutorService.shutdown(); super.tearDown(); } @Test public void testExecute() { assertTrue(size(strategy.execute()) > 0, "Expected one or more elements"); } public void testExecuteConcurrentlyWithExecutorService() { assertTrue(size(strategy.execute(testExecutorService)) > 0, "Expected one or more elements"); } public void testExecuteConcurrentlyWithListeningExecutorService() { assertTrue(size(strategy.execute(testListeningExecutorService)) > 0, "Expected one or more elements"); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/strategy/internal/ListNodesInEnvironmentImplLiveTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.strategy.internal; import static com.google.common.collect.Iterables.size; import static org.testng.Assert.assertTrue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import org.jclouds.chef.internal.BaseChefLiveTest; import org.testng.annotations.AfterClass; import org.testng.annotations.Test; import com.google.common.collect.ImmutableSet; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.MoreExecutors; /** * Tests behavior of {@code ListNodesInEnvironmentImpl} strategies */ @Test(groups = "live", testName = "ListNodesInEnvironmentImplLiveTest") public class ListNodesInEnvironmentImplLiveTest extends BaseChefLiveTest { private ListNodesInEnvironmentImpl strategy; private CreateNodeAndPopulateAutomaticAttributesImpl creator; private ExecutorService testExecutorService; private ListeningExecutorService testListeningExecutorService; @Override protected void initialize() { super.initialize(); this.prefix = this.prefix + "-" + this.hashCode(); this.creator = injector.getInstance(CreateNodeAndPopulateAutomaticAttributesImpl.class); this.strategy = injector.getInstance(ListNodesInEnvironmentImpl.class); creator.execute(prefix, ImmutableSet.of()); creator.execute(prefix + 1, ImmutableSet.of()); this.testExecutorService = Executors.newFixedThreadPool(5); this.testListeningExecutorService = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(5)); } @AfterClass(groups = { "integration", "live" }) @Override protected void tearDown() { api.deleteNode(prefix); api.deleteNode(prefix + 1); this.testExecutorService.shutdown(); this.testListeningExecutorService.shutdown(); super.tearDown(); } @Test public void testExecute() { assertTrue(size(strategy.execute("_default")) > 0, "Expected one or more elements"); } @Test public void testExecuteConcurrentlyWithExecutorService() { assertTrue(size(strategy.execute(testExecutorService, "_default")) > 0, "Expected one or more elements"); } @Test public void testExecuteConcurrentlyWithListeningExecutorService() { assertTrue(size(strategy.execute(testListeningExecutorService, "_default")) > 0, "Expected one or more elements"); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/strategy/internal/UpdateAutomaticAttributesOnNodeImplLiveTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.strategy.internal; import static org.testng.Assert.assertEquals; import java.util.Set; import org.jclouds.chef.domain.Node; import org.jclouds.chef.internal.BaseChefLiveTest; import org.jclouds.ohai.config.OhaiModule.CurrentUserProvider; import org.testng.annotations.Test; import com.google.common.collect.ImmutableSet; /** * Tests behavior of {@code UpdateAutomaticAttributesOnNodeImpl} strategies */ @Test(groups = "live", testName = "UpdateAutomaticAttributesOnNodeImplLiveTest") public class UpdateAutomaticAttributesOnNodeImplLiveTest extends BaseChefLiveTest { private CurrentUserProvider currentUserProvider; private UpdateAutomaticAttributesOnNodeImpl strategy; @Override protected void initialize() { super.initialize(); this.prefix = this.prefix + "-" + this.hashCode(); this.currentUserProvider = injector.getInstance(CurrentUserProvider.class); this.strategy = injector.getInstance(UpdateAutomaticAttributesOnNodeImpl.class); } @Test public void testExecute() { Set runList = ImmutableSet.of("role[" + prefix + "]"); try { api.createNode(Node.builder().name(prefix).runList(runList).environment("_default").build()); strategy.execute(prefix); Node node = api.getNode(prefix); assertEquals(node.getName(), prefix); assertEquals(node.getRunList(), runList); assertEquals(node.getAutomaticAttributes().get("current_user").toString(), currentUserProvider.get().toString()); } finally { api.deleteNode(prefix); } } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/strategy/internal/UpdateAutomaticAttributesOnNodeImplTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.strategy.internal; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; import java.util.Map; import org.jclouds.chef.ChefApi; import org.jclouds.chef.domain.Node; import org.jclouds.domain.JsonBall; import org.testng.annotations.Test; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; import com.google.common.collect.ImmutableMap; /** * Tests behavior of {@code UpdateAutomaticAttributesOnNodeImpl} */ @Test(groups = { "unit" }) public class UpdateAutomaticAttributesOnNodeImplTest { @Test public void test() { ChefApi chef = createMock(ChefApi.class); Map automatic = ImmutableMap. of(); Supplier> automaticSupplier = Suppliers.> ofInstance(automatic); Node node = Node.builder().name("name").environment("_default").build(); Node nodeWithAutomatic = Node.builder().name("name").environment("_default").automaticAttributes(automatic) .build(); expect(chef.getNode("name")).andReturn(node); expect(chef.updateNode(nodeWithAutomatic)).andReturn(null); replay(chef); UpdateAutomaticAttributesOnNodeImpl updater = new UpdateAutomaticAttributesOnNodeImpl(chef, automaticSupplier); updater.execute("name"); verify(chef); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/suppliers/ChefVersionSupplierTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.suppliers; import static org.jclouds.chef.suppliers.ChefVersionSupplier.FALLBACK_VERSION; import static org.testng.Assert.assertEquals; import org.testng.annotations.Test; /** * Unit tests for the {@link ChefVersionSupplier} class. */ @Test(groups = "unit", testName = "ChefVersionSupplierTest") public class ChefVersionSupplierTest { public void testReturnsDefaultVersion() { assertEquals(new ChefVersionSupplier("15").get(), FALLBACK_VERSION); assertEquals(new ChefVersionSupplier("0").get(), FALLBACK_VERSION); assertEquals(new ChefVersionSupplier("0.").get(), FALLBACK_VERSION); } public void testReturnsMajorVersionIfNotZero() { assertEquals(new ChefVersionSupplier("11.6").get().intValue(), 11); assertEquals(new ChefVersionSupplier("11.6.0").get().intValue(), 11); assertEquals(new ChefVersionSupplier("11.6.0.1").get().intValue(), 11); } public void testReturnsMinorVersionIfMajorIsZero() { assertEquals(new ChefVersionSupplier("0.9").get().intValue(), 9); assertEquals(new ChefVersionSupplier("0.9.8").get().intValue(), 9); assertEquals(new ChefVersionSupplier("0.9.8.2").get().intValue(), 9); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/util/ChefUtilsTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.util; import static org.testng.Assert.assertEquals; import java.util.Date; import java.util.NoSuchElementException; import org.jclouds.domain.JsonBall; import org.testng.annotations.Test; import com.google.common.collect.ImmutableList; /** * Tests behavior of {@code ChefUtils} */ @Test(groups = { "unit" }, singleThreaded = true) public class ChefUtilsTest { public static long millis = 1280251180727L; public static String millisString = "1280251180727"; public static Date now = new Date(1280251180727L); public void testToOhaiTime() { assertEquals(ChefUtils.toOhaiTime(millis).toString(), millisString); } public void testFromOhaiTime() { assertEquals(ChefUtils.fromOhaiTime(new JsonBall(millisString)), now); } @Test(expectedExceptions = NoSuchElementException.class) public void testFindRoleInRunListThrowsNoSuchElementOnRecipe() { ChefUtils.findRoleInRunList(ImmutableList.of("recipe[java]")); } public void testFindRoleInRunList() { assertEquals(ChefUtils.findRoleInRunList(ImmutableList.of("role[prod]")), "prod"); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/chef/util/RunListBuilderTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.chef.util; import static org.testng.Assert.assertEquals; import org.testng.annotations.Test; import com.google.common.collect.ImmutableList; /** * Tests possible uses of RunListBuilder */ public class RunListBuilderTest { @Test public void testRecipeAndRole() { RunListBuilder options = new RunListBuilder(); options.addRecipe("recipe").addRole("role"); assertEquals(options.build(), ImmutableList.of("recipe[recipe]", "role[role]")); } @Test public void testRecipe() { RunListBuilder options = new RunListBuilder(); options.addRecipe("test"); assertEquals(options.build(), ImmutableList.of("recipe[test]")); } @Test public void testRecipes() { RunListBuilder options = new RunListBuilder(); options.addRecipes("test", "test2"); assertEquals(options.build(), ImmutableList.of("recipe[test]", "recipe[test2]")); } @Test public void testRole() { RunListBuilder options = new RunListBuilder(); options.addRole("test"); assertEquals(options.build(), ImmutableList.of("role[test]")); } @Test public void testRoles() { RunListBuilder options = new RunListBuilder(); options.addRoles("test", "test2"); assertEquals(options.build(), ImmutableList.of("role[test]", "role[test2]")); } @Test public void testNoneRecipe() { RunListBuilder options = new RunListBuilder(); assertEquals(options.build(), ImmutableList. of()); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/ohai/config/JMXTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.ohai.config; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; import static org.testng.Assert.assertEquals; import java.lang.management.RuntimeMXBean; import java.util.Map; import jakarta.inject.Inject; import org.jclouds.chef.ChefApiMetadata; import org.jclouds.chef.config.ChefParserModule; import org.jclouds.domain.JsonBall; import org.jclouds.json.Json; import org.jclouds.json.config.GsonModule; import org.jclouds.ohai.Automatic; import org.jclouds.rest.annotations.ApiVersion; import org.testng.annotations.Test; import com.google.common.base.Supplier; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; /** * Tests behavior of {@code JMX} */ @Test(groups = { "unit" }) public class JMXTest { @Test public void test() { final RuntimeMXBean runtime = createMock(RuntimeMXBean.class); expect(runtime.getUptime()).andReturn(69876000L); replay(runtime); Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION); } }, new ChefParserModule(), new GsonModule(), new JMXOhaiModule() { @Override protected RuntimeMXBean provideRuntimeMXBean() { return runtime; } }); Json json = injector.getInstance(Json.class); Ohai ohai = injector.getInstance(Ohai.class); assertEquals(json.toJson(ohai.ohai.get().get("uptime_seconds")), "69876"); } static class Ohai { private Supplier> ohai; @Inject public Ohai(@Automatic Supplier> ohai) { this.ohai = ohai; } } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/ohai/config/OhaiModuleTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.ohai.config; import static org.jclouds.chef.util.ChefUtils.ohaiAutomaticAttributeBinder; import static org.testng.Assert.assertEquals; import java.net.SocketException; import java.util.Map; import java.util.Properties; import jakarta.inject.Inject; import org.jclouds.chef.ChefApiMetadata; import org.jclouds.chef.config.ChefParserModule; import org.jclouds.domain.JsonBall; import org.jclouds.json.Json; import org.jclouds.json.config.GsonModule; import org.jclouds.ohai.Automatic; import org.jclouds.rest.annotations.ApiVersion; import org.testng.annotations.Test; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.TypeLiteral; import com.google.inject.multibindings.MapBinder; import com.google.inject.util.Providers; /** * Tests behavior of {@code OhaiModule} */ @Test(groups = { "unit" }) public class OhaiModuleTest { @Test public void test() throws SocketException { final Properties sysProperties = new Properties(); sysProperties.setProperty("os.name", "Mac OS X"); sysProperties.setProperty("os.version", "10.3.0"); sysProperties.setProperty("user.name", "user"); Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION); } }, new ChefParserModule(), new GsonModule(), new OhaiModule() { @Override protected Long millis() { return 127999291932529L; } @Override protected Properties systemProperties() { return sysProperties; } }); Ohai ohai = injector.getInstance(Ohai.class); Json json = injector.getInstance(Json.class); assertEquals( json.toJson(ohai.ohai.get(), new TypeLiteral>() { }.getType()), "{\"ohai_time\":127999291932529,\"platform\":\"macosx\",\"platform_version\":\"10.3.0\",\"current_user\":\"user\",\"jvm\":{\"system\":{\"user.name\":\"user\",\"os.version\":\"10.3.0\",\"os.name\":\"Mac OS X\"}}}"); } public void test2modules() throws SocketException { final Properties sysProperties = new Properties(); sysProperties.setProperty("os.name", "Mac OS X"); sysProperties.setProperty("os.version", "10.3.0"); sysProperties.setProperty("user.name", "user"); Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION); } }, new ChefParserModule(), new GsonModule(), new OhaiModule() { @Override protected Long millis() { return 1279992919L; } @Override protected Properties systemProperties() { return sysProperties; } }, new AbstractModule() { @Override protected void configure() { MapBinder> mapbinder = ohaiAutomaticAttributeBinder(binder()); mapbinder.addBinding("test").toProvider( Providers.of(Suppliers.ofInstance(new JsonBall("{\"prop1\":\"test1\"}")))); } }, new AbstractModule() { @Override protected void configure() { MapBinder> mapbinder = ohaiAutomaticAttributeBinder(binder()); mapbinder.addBinding("test").toProvider( Providers.of(Suppliers.ofInstance(new JsonBall("{\"prop2\":\"test2\"}")))); } }); Ohai ohai = injector.getInstance(Ohai.class); Json json = injector.getInstance(Json.class); assertEquals( json.toJson(ohai.ohai.get(), new TypeLiteral>() { }.getType()), "{\"ohai_time\":1279992919,\"platform\":\"macosx\",\"platform_version\":\"10.3.0\",\"current_user\":\"user\",\"test\":{\"prop1\":\"test1\",\"prop2\":\"test2\"},\"jvm\":{\"system\":{\"user.name\":\"user\",\"os.version\":\"10.3.0\",\"os.name\":\"Mac OS X\"}}}"); } static class Ohai { private Supplier> ohai; @Inject public Ohai(@Automatic Supplier> ohai) { this.ohai = ohai; } } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/ohai/functions/ByteArrayToMacAddressTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.ohai.functions; import static com.google.common.io.BaseEncoding.base16; import static org.testng.Assert.assertEquals; import org.testng.annotations.Test; /** * Tests behavior of {@code ByteArrayToMacAddress} */ @Test(groups = { "unit" }, singleThreaded = true) public class ByteArrayToMacAddressTest { public void test() { assertEquals(new ByteArrayToMacAddress().apply(base16().lowerCase().decode("0026bb09e6c4")), "00:26:bb:09:e6:c4"); } } ================================================ FILE: apis/chef/src/test/java/org/jclouds/ohai/functions/NestSlashKeysTest.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.ohai.functions; import static org.testng.Assert.assertEquals; import java.io.IOException; import org.jclouds.chef.ChefApiMetadata; import org.jclouds.chef.config.ChefParserModule; import org.jclouds.domain.JsonBall; import org.jclouds.json.Json; import org.jclouds.json.config.GsonModule; import org.jclouds.rest.annotations.ApiVersion; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; import com.google.common.collect.ImmutableListMultimap; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Injector; /** * Tests behavior of {@code NestSlashKeys} */ @Test(groups = "unit", testName = "NestSlashKeysTest") public class NestSlashKeysTest { private NestSlashKeys converter; private Json json; @BeforeTest protected void setUpInjector() throws IOException { Injector injector = Guice.createInjector(new AbstractModule() { @Override protected void configure() { bind(String.class).annotatedWith(ApiVersion.class).toInstance(ChefApiMetadata.DEFAULT_API_VERSION); } }, new ChefParserModule(), new GsonModule()); converter = injector.getInstance(NestSlashKeys.class); json = injector.getInstance(Json.class); } @Test public void testBase() { assertEquals( json.toJson(converter.apply(ImmutableListMultimap.> of("java", Suppliers.ofInstance(new JsonBall("java"))))), "{\"java\":\"java\"}"); } @Test(expectedExceptions = IllegalArgumentException.class) public void testIllegal() { json.toJson(converter.apply(ImmutableListMultimap.> of("java", Suppliers.ofInstance(new JsonBall("java")), "java/system", Suppliers.ofInstance(new JsonBall("system"))))); } @Test public void testOne() { assertEquals( json.toJson(converter.apply(ImmutableListMultimap.> of("java", Suppliers.ofInstance(new JsonBall("{\"time\":\"time\"}")), "java/system", Suppliers.ofInstance(new JsonBall("system"))))), "{\"java\":{\"time\":\"time\",\"system\":\"system\"}}"); } @Test public void testOneDuplicate() { assertEquals( json.toJson(converter.apply(ImmutableListMultimap.> of("java", Suppliers.ofInstance(new JsonBall("{\"time\":\"time\"}")), "java", Suppliers.ofInstance(new JsonBall("{\"system\":\"system\"}"))))), "{\"java\":{\"time\":\"time\",\"system\":\"system\"}}"); } @Test public void testMerge() { assertEquals( json.toJson(converter.apply(ImmutableListMultimap.> of("java", Suppliers.ofInstance(new JsonBall("{\"time\":{\"1\":\"hello\"}}")), "java/time", Suppliers.ofInstance(new JsonBall("{\"2\":\"goodbye\"}"))))), "{\"java\":{\"time\":{\"1\":\"hello\",\"2\":\"goodbye\"}}}"); } @Test public void testMergeNestedTwice() { assertEquals( json.toJson(converter.apply(ImmutableListMultimap.> of("java", Suppliers.ofInstance(new JsonBall("{\"time\":{\"1\":\"hello\"}}")), "java", Suppliers.ofInstance(new JsonBall("{\"time\":{\"2\":\"goodbye\"}}"))))), "{\"java\":{\"time\":{\"1\":\"hello\",\"2\":\"goodbye\"}}}"); } @Test public void testReplaceList() { assertEquals( json.toJson(converter.apply(ImmutableListMultimap.> of("java", Suppliers.ofInstance(new JsonBall("{\"time\":{\"1\":[\"hello\"]}}")), "java/time", Suppliers.ofInstance(new JsonBall("{\"1\":[\"goodbye\"]}"))))), "{\"java\":{\"time\":{\"1\":[\"goodbye\"]}}}"); } } ================================================ FILE: apis/chef/src/test/resources/apache-chef-demo-cookbook.json ================================================ { "definitions": [], "name": "apache-chef-demo-0.0.0", "attributes": [], "files": [], "json_class": "Chef::CookbookVersion", "providers": [], "metadata": { "dependencies": {}, "name": "apache-chef-demo", "maintainer_email": "youremail@example.com", "attributes": {}, "license": "Apache v2.0", "maintainer": "Your Name", "suggestions": {}, "platforms": {}, "long_description": "", "recommendations": {}, "version": "0.0.0", "groupings": { "one": { "title": "One title", "description": "One description" }, "two": { "title": "Two title", "description": "Two description" } }, "recipes": {}, "conflicting": {}, "description": "A fabulous new cookbook", "replacing": {}, "providing": {} }, "libraries": [], "resources": [], "templates": [], "cookbook_name": "apache-chef-demo", "version": "0.0.0", "recipes": [], "root_files": [{ "name": "README", "url": "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-11637f98942eafbf49c71b7f2f048b78?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277766181&Signature=zgpNl6wSxjTNovqZu2nJq0JztU8%3D", "checksum": "11637f98942eafbf49c71b7f2f048b78", "path": "README", "specificity": "default" }, { "name": "Rakefile", "url": "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-ebcf925a1651b4e04b9cd8aac2bc54eb?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277766181&Signature=EFzzDSKKytTl7b%2FxrCeNLh05zj4%3D", "checksum": "ebcf925a1651b4e04b9cd8aac2bc54eb", "path": "Rakefile", "specificity": "default" }], "chef_type": "cookbook_version" } ================================================ FILE: apis/chef/src/test/resources/bootstrap-env-noattrs.sh ================================================ mkdir -p /etc/chef cat > /etc/chef/client.rb <<-'END_OF_JCLOUDS_FILE' require 'rubygems' require 'ohai' o = Ohai::System.new o.all_plugins node_name "foo-" + o[:ipaddress] log_level :info log_location STDOUT validation_client_name "chef-validator" chef_server_url "http://localhost:4000" environment "env" END_OF_JCLOUDS_FILE cat > /etc/chef/validation.pem <<-'END_OF_JCLOUDS_FILE' -----BEGIN PRIVATE KEY----- LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVB eWIyWkpKcUdtMEtLUis4bmZRSk5zU2QrRjl0WE5NVjdDZk9jVzZqc3FzOEVaZ2lW ClIwOWhEMUlZT2o0WXFNMHFKT05sZ3lnNHhSV2V3ZFNHN1FUUGoxbEpwVkFpZGE5 c1h5MitrenlhZ1pBMUFtME8KWmNicWI1aG9lSURnY1grZURhNzlzMHUwRG9tamNm TzlFS2h2SExCeit6TSszUXFQUmtQVjhuWVRiZnMrSGpWegp6T1U2RDFCMFhSMytJ UFpabDJBbldzMmQwcWhuU3RIY0RVdm5SVlEwUDQ4Mll3TjlWZ2NlT1p0cFB6MERD S0VKCjVUeDVTVHViOGswL3p0L1ZBTUhRYWZMU3VRTUxkMnM0Wkx1T1pwdE4vL3VB c1RteGlyZXFkMzd6KzhaVGRCYkoKOExFcEoraUNYdVNmbTVhVWg3aXc2b3h2VG9Z MkFMNTMraksyVVFJREFRQUJBb0lCQVFEQTg4QjNpL3hXbjB2WApCVnhGYW1DWW9l Y3VOakd3WFhrU3laZXc2MTZBK0VPQ3U0N2JoNGFUdXJkRmJZTDBZRmFBdGFXdnps YU4yZUhnCkRiK0hEdVRlZkUyOStXa2NHazZTc2hQbWl6NVQwWE9DQUlDV3c2d1NW RGtIbUd3UzRqWnZiQUZtN1c4bndHazkKWWh4Z3hGaVJuZ3N3SlpGb3BPTG9GNVdY czJ0ZDhndUlZTnNsTXBvN3R1NTBpRm5CSHdLTzJac1BBazh0OW5uUwp4bERhdkty dXltRW1xSENyMytkdGlvNWVhZW5KY3AzZmpvWEJRT0tVazNpcElJMjlYUkI4TnFl Q1ZWLzdLeHdxCmNrcU9CRWJSd0JjbGNreUliRCtSaUFnS3ZPZWxPUmpFaUU5UjQy dnVxdnhSQTZrOWtkOW83dXRsWDBBVXRwRW4KM2daYzZMZXBBb0dCQVA5YWVsNVk3 NStzSzJKSlVOT09oTzhhZTQ1Y2RzaWxwMnlJMFgrVUJhU3VRczIrZHlQcAprcEVI QXhkNHBtbVN2bi84YzlUbEVaaHIrcVliQUJYVlBsRG5jeHBJdXcyQWpiazdzL1M0 WGFTS3NScXBYTDU3CnpqL1FPcUxrUms4K09WVjlxNmxNZVFOcUx0RWoxdTZKUHZp WDcwUm8rRlF0UnR0Tk9ZYmZkUC9mQW9HQkFNcEEKWGpSNXdvVjVzVWIrUkVnOXZF dVlvOFJTeU9hcnhxS0ZDSVhWVU5zTE94KzIyK0FLNCtDUXBidWVXTjdqb3RybApZ RDZ1VDZzdldpM0FBQzdraVkwVUkvZmpWUFJDVWk4dFZvUVVFMFRhVTVWTElUYVlP QitXL2JCYURFNE05NTYwCjFOdURXTzkwYmFBNWRmVTQ0aXV6dmEwMnJHSlhLOStu UzNvOG5rL1BBb0dCQUxPTDZkam5EZTRtd0FhRzZKY28KY2Q0eHI4amt5UHpDUlp1 eUJDU0Jid3BoSVVYTGM3aERwclBreTA2NG5jSkQxVURtd0lka1hkL2ZwTWtnMlFt QQovQ1VrNkxFRmpNaXNxSG9qT2FDTDlnUVpKUGhMTjVRVU4yeDFQSldHanMxdlFo OFRreDBpVVVDT2E4YlFQWE5SCiszNE9Uc1c2VFVuYTRDU1pBeWNMZmhmZkFvR0JB SWdnVnNlZkJDdnVRa0YwTmVVaG1EQ1JaZmhuZDh5NTVSSFIKMUhDdnFLSWxwdity aGNYL3pteUJMdXRlb3BZeVJKUnNPaUUyRlcwMGk4K3JJUFJ1NFozUTVueWJ4N3cz UHpWOQpvSE41UjViYUU5T3lJNEtwWld6dHBZWWl0WkY2N05jbkF2VlVMSEhPdlZK UUduS1lmTEhKWW1ySkY3R0Exb2pNCkF1TWRGYmpGQW9HQVB4VWh4d0Z5OGdhcUJh aEtVRVpuNEY4MUhGUDVpaEdoa1Q0UUw2QUZQTzJlK0poSUdqdVIKMjcrODVoY0Zx UStISFZ0RnNtODFiL2ErUjdQNFV1Q1JnYzhlQ2p4UU1vSjFYbDRuN1ZialBiSE1u SU4wUnl2ZApPNFpwV0RXWW5DTzAyMUpUT1VVT0o0Si95MDQxNkJ2a3cwejU5eTdz Tlg3d0RCQkhIYksvWENjPQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo= -----END PRIVATE KEY----- END_OF_JCLOUDS_FILE cat > /etc/chef/first-boot.json <<-'END_OF_JCLOUDS_FILE' {"run_list":["recipe[apache2]","role[webserver]"]} END_OF_JCLOUDS_FILE chef-client -j /etc/chef/first-boot.json ================================================ FILE: apis/chef/src/test/resources/bootstrap-env.sh ================================================ mkdir -p /etc/chef cat > /etc/chef/client.rb <<-'END_OF_JCLOUDS_FILE' require 'rubygems' require 'ohai' o = Ohai::System.new o.all_plugins node_name "foo-" + o[:ipaddress] log_level :info log_location STDOUT validation_client_name "chef-validator" chef_server_url "http://localhost:4000" environment "env" END_OF_JCLOUDS_FILE cat > /etc/chef/validation.pem <<-'END_OF_JCLOUDS_FILE' -----BEGIN PRIVATE KEY----- LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVB eWIyWkpKcUdtMEtLUis4bmZRSk5zU2QrRjl0WE5NVjdDZk9jVzZqc3FzOEVaZ2lW ClIwOWhEMUlZT2o0WXFNMHFKT05sZ3lnNHhSV2V3ZFNHN1FUUGoxbEpwVkFpZGE5 c1h5MitrenlhZ1pBMUFtME8KWmNicWI1aG9lSURnY1grZURhNzlzMHUwRG9tamNm TzlFS2h2SExCeit6TSszUXFQUmtQVjhuWVRiZnMrSGpWegp6T1U2RDFCMFhSMytJ UFpabDJBbldzMmQwcWhuU3RIY0RVdm5SVlEwUDQ4Mll3TjlWZ2NlT1p0cFB6MERD S0VKCjVUeDVTVHViOGswL3p0L1ZBTUhRYWZMU3VRTUxkMnM0Wkx1T1pwdE4vL3VB c1RteGlyZXFkMzd6KzhaVGRCYkoKOExFcEoraUNYdVNmbTVhVWg3aXc2b3h2VG9Z MkFMNTMraksyVVFJREFRQUJBb0lCQVFEQTg4QjNpL3hXbjB2WApCVnhGYW1DWW9l Y3VOakd3WFhrU3laZXc2MTZBK0VPQ3U0N2JoNGFUdXJkRmJZTDBZRmFBdGFXdnps YU4yZUhnCkRiK0hEdVRlZkUyOStXa2NHazZTc2hQbWl6NVQwWE9DQUlDV3c2d1NW RGtIbUd3UzRqWnZiQUZtN1c4bndHazkKWWh4Z3hGaVJuZ3N3SlpGb3BPTG9GNVdY czJ0ZDhndUlZTnNsTXBvN3R1NTBpRm5CSHdLTzJac1BBazh0OW5uUwp4bERhdkty dXltRW1xSENyMytkdGlvNWVhZW5KY3AzZmpvWEJRT0tVazNpcElJMjlYUkI4TnFl Q1ZWLzdLeHdxCmNrcU9CRWJSd0JjbGNreUliRCtSaUFnS3ZPZWxPUmpFaUU5UjQy dnVxdnhSQTZrOWtkOW83dXRsWDBBVXRwRW4KM2daYzZMZXBBb0dCQVA5YWVsNVk3 NStzSzJKSlVOT09oTzhhZTQ1Y2RzaWxwMnlJMFgrVUJhU3VRczIrZHlQcAprcEVI QXhkNHBtbVN2bi84YzlUbEVaaHIrcVliQUJYVlBsRG5jeHBJdXcyQWpiazdzL1M0 WGFTS3NScXBYTDU3CnpqL1FPcUxrUms4K09WVjlxNmxNZVFOcUx0RWoxdTZKUHZp WDcwUm8rRlF0UnR0Tk9ZYmZkUC9mQW9HQkFNcEEKWGpSNXdvVjVzVWIrUkVnOXZF dVlvOFJTeU9hcnhxS0ZDSVhWVU5zTE94KzIyK0FLNCtDUXBidWVXTjdqb3RybApZ RDZ1VDZzdldpM0FBQzdraVkwVUkvZmpWUFJDVWk4dFZvUVVFMFRhVTVWTElUYVlP QitXL2JCYURFNE05NTYwCjFOdURXTzkwYmFBNWRmVTQ0aXV6dmEwMnJHSlhLOStu UzNvOG5rL1BBb0dCQUxPTDZkam5EZTRtd0FhRzZKY28KY2Q0eHI4amt5UHpDUlp1 eUJDU0Jid3BoSVVYTGM3aERwclBreTA2NG5jSkQxVURtd0lka1hkL2ZwTWtnMlFt QQovQ1VrNkxFRmpNaXNxSG9qT2FDTDlnUVpKUGhMTjVRVU4yeDFQSldHanMxdlFo OFRreDBpVVVDT2E4YlFQWE5SCiszNE9Uc1c2VFVuYTRDU1pBeWNMZmhmZkFvR0JB SWdnVnNlZkJDdnVRa0YwTmVVaG1EQ1JaZmhuZDh5NTVSSFIKMUhDdnFLSWxwdity aGNYL3pteUJMdXRlb3BZeVJKUnNPaUUyRlcwMGk4K3JJUFJ1NFozUTVueWJ4N3cz UHpWOQpvSE41UjViYUU5T3lJNEtwWld6dHBZWWl0WkY2N05jbkF2VlVMSEhPdlZK UUduS1lmTEhKWW1ySkY3R0Exb2pNCkF1TWRGYmpGQW9HQVB4VWh4d0Z5OGdhcUJh aEtVRVpuNEY4MUhGUDVpaEdoa1Q0UUw2QUZQTzJlK0poSUdqdVIKMjcrODVoY0Zx UStISFZ0RnNtODFiL2ErUjdQNFV1Q1JnYzhlQ2p4UU1vSjFYbDRuN1ZialBiSE1u SU4wUnl2ZApPNFpwV0RXWW5DTzAyMUpUT1VVT0o0Si95MDQxNkJ2a3cwejU5eTdz Tlg3d0RCQkhIYksvWENjPQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo= -----END PRIVATE KEY----- END_OF_JCLOUDS_FILE cat > /etc/chef/first-boot.json <<-'END_OF_JCLOUDS_FILE' {"tomcat6":{"ssl_port":8433},"run_list":["recipe[apache2]","role[webserver]"]} END_OF_JCLOUDS_FILE chef-client -j /etc/chef/first-boot.json ================================================ FILE: apis/chef/src/test/resources/bootstrap-node-env.sh ================================================ mkdir -p /etc/chef cat > /etc/chef/client.rb <<-'END_OF_JCLOUDS_FILE' require 'rubygems' require 'ohai' o = Ohai::System.new o.all_plugins node_name "bar" log_level :info log_location STDOUT validation_client_name "chef-validator" chef_server_url "http://localhost:4000" environment "env" END_OF_JCLOUDS_FILE cat > /etc/chef/validation.pem <<-'END_OF_JCLOUDS_FILE' -----BEGIN PRIVATE KEY----- LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVB eWIyWkpKcUdtMEtLUis4bmZRSk5zU2QrRjl0WE5NVjdDZk9jVzZqc3FzOEVaZ2lW ClIwOWhEMUlZT2o0WXFNMHFKT05sZ3lnNHhSV2V3ZFNHN1FUUGoxbEpwVkFpZGE5 c1h5MitrenlhZ1pBMUFtME8KWmNicWI1aG9lSURnY1grZURhNzlzMHUwRG9tamNm TzlFS2h2SExCeit6TSszUXFQUmtQVjhuWVRiZnMrSGpWegp6T1U2RDFCMFhSMytJ UFpabDJBbldzMmQwcWhuU3RIY0RVdm5SVlEwUDQ4Mll3TjlWZ2NlT1p0cFB6MERD S0VKCjVUeDVTVHViOGswL3p0L1ZBTUhRYWZMU3VRTUxkMnM0Wkx1T1pwdE4vL3VB c1RteGlyZXFkMzd6KzhaVGRCYkoKOExFcEoraUNYdVNmbTVhVWg3aXc2b3h2VG9Z MkFMNTMraksyVVFJREFRQUJBb0lCQVFEQTg4QjNpL3hXbjB2WApCVnhGYW1DWW9l Y3VOakd3WFhrU3laZXc2MTZBK0VPQ3U0N2JoNGFUdXJkRmJZTDBZRmFBdGFXdnps YU4yZUhnCkRiK0hEdVRlZkUyOStXa2NHazZTc2hQbWl6NVQwWE9DQUlDV3c2d1NW RGtIbUd3UzRqWnZiQUZtN1c4bndHazkKWWh4Z3hGaVJuZ3N3SlpGb3BPTG9GNVdY czJ0ZDhndUlZTnNsTXBvN3R1NTBpRm5CSHdLTzJac1BBazh0OW5uUwp4bERhdkty dXltRW1xSENyMytkdGlvNWVhZW5KY3AzZmpvWEJRT0tVazNpcElJMjlYUkI4TnFl Q1ZWLzdLeHdxCmNrcU9CRWJSd0JjbGNreUliRCtSaUFnS3ZPZWxPUmpFaUU5UjQy dnVxdnhSQTZrOWtkOW83dXRsWDBBVXRwRW4KM2daYzZMZXBBb0dCQVA5YWVsNVk3 NStzSzJKSlVOT09oTzhhZTQ1Y2RzaWxwMnlJMFgrVUJhU3VRczIrZHlQcAprcEVI QXhkNHBtbVN2bi84YzlUbEVaaHIrcVliQUJYVlBsRG5jeHBJdXcyQWpiazdzL1M0 WGFTS3NScXBYTDU3CnpqL1FPcUxrUms4K09WVjlxNmxNZVFOcUx0RWoxdTZKUHZp WDcwUm8rRlF0UnR0Tk9ZYmZkUC9mQW9HQkFNcEEKWGpSNXdvVjVzVWIrUkVnOXZF dVlvOFJTeU9hcnhxS0ZDSVhWVU5zTE94KzIyK0FLNCtDUXBidWVXTjdqb3RybApZ RDZ1VDZzdldpM0FBQzdraVkwVUkvZmpWUFJDVWk4dFZvUVVFMFRhVTVWTElUYVlP QitXL2JCYURFNE05NTYwCjFOdURXTzkwYmFBNWRmVTQ0aXV6dmEwMnJHSlhLOStu UzNvOG5rL1BBb0dCQUxPTDZkam5EZTRtd0FhRzZKY28KY2Q0eHI4amt5UHpDUlp1 eUJDU0Jid3BoSVVYTGM3aERwclBreTA2NG5jSkQxVURtd0lka1hkL2ZwTWtnMlFt QQovQ1VrNkxFRmpNaXNxSG9qT2FDTDlnUVpKUGhMTjVRVU4yeDFQSldHanMxdlFo OFRreDBpVVVDT2E4YlFQWE5SCiszNE9Uc1c2VFVuYTRDU1pBeWNMZmhmZkFvR0JB SWdnVnNlZkJDdnVRa0YwTmVVaG1EQ1JaZmhuZDh5NTVSSFIKMUhDdnFLSWxwdity aGNYL3pteUJMdXRlb3BZeVJKUnNPaUUyRlcwMGk4K3JJUFJ1NFozUTVueWJ4N3cz UHpWOQpvSE41UjViYUU5T3lJNEtwWld6dHBZWWl0WkY2N05jbkF2VlVMSEhPdlZK UUduS1lmTEhKWW1ySkY3R0Exb2pNCkF1TWRGYmpGQW9HQVB4VWh4d0Z5OGdhcUJh aEtVRVpuNEY4MUhGUDVpaEdoa1Q0UUw2QUZQTzJlK0poSUdqdVIKMjcrODVoY0Zx UStISFZ0RnNtODFiL2ErUjdQNFV1Q1JnYzhlQ2p4UU1vSjFYbDRuN1ZialBiSE1u SU4wUnl2ZApPNFpwV0RXWW5DTzAyMUpUT1VVT0o0Si95MDQxNkJ2a3cwejU5eTdz Tlg3d0RCQkhIYksvWENjPQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo= -----END PRIVATE KEY----- END_OF_JCLOUDS_FILE cat > /etc/chef/first-boot.json <<-'END_OF_JCLOUDS_FILE' {"tomcat6":{"ssl_port":8433},"run_list":["recipe[apache2]","role[webserver]"]} END_OF_JCLOUDS_FILE chef-client -j /etc/chef/first-boot.json ================================================ FILE: apis/chef/src/test/resources/bootstrap-ssl.sh ================================================ mkdir -p /etc/chef cat > /etc/chef/chef-server.crt <<-'END_OF_JCLOUDS_FILE' -----BEGIN CERTIFICATE----- MIIFDTCCA/WgAwIBAgIQBZ8R1sZP2Lbc8x554UUQ2DANBgkqhkiG9w0BAQsFADBN MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMScwJQYDVQQDEx5E aWdpQ2VydCBTSEEyIFNlY3VyZSBTZXJ2ZXIgQ0EwHhcNMTQxMTEwMDAwMDAwWhcN MTcxMTE0MTIwMDAwWjBlMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv bjEQMA4GA1UEBxMHU2VhdHRsZTEbMBkGA1UEChMSQ2hlZiBTb2Z0d2FyZSwgSW5j MRIwEAYDVQQDDAkqLmNoZWYuaW8wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK AoIBAQC3xCIczkV10O5jTDpbd4YlPLC6kfnVoOkno2N/OOlcLQu3ulj/Lj1j4r6e 2XthJLcFgTO+y+1/IKnnpLKDfkx1YngWEBXEBP+MrrpDUKKs053s45/bI9QBPISA tXgnYxMH9Glo6FWWd13TUq++OKGw1p1wazH64XK4MAf5y/lkmWXIWumNuO35ZqtB ME3wJISwVHzHB2CQjlDklt+Mb0APEiIFIZflgu9JNBYzLdvUtxiz15FUZQI7SsYL TfXOD1KBNMWqN8snG2e5gRAzB2D161DFvAZt8OiYUe+3QurNlTYVzeHv1ok6UqgM ZcLzg8m801rRip0D7FCGvMCU/ktdAgMBAAGjggHPMIIByzAfBgNVHSMEGDAWgBQP gGEcgjFh1S8o541GOLQs4cbZ4jAdBgNVHQ4EFgQUwldjw4Pb4HV+wxGZ7MSSRh+d pm4wHQYDVR0RBBYwFIIJKi5jaGVmLmlvggdjaGVmLmlvMA4GA1UdDwEB/wQEAwIF oDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwawYDVR0fBGQwYjAvoC2g K4YpaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NzY2Etc2hhMi1nMy5jcmwwL6At oCuGKWh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9zc2NhLXNoYTItZzMuY3JsMEIG A1UdIAQ7MDkwNwYJYIZIAYb9bAEBMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3 LmRpZ2ljZXJ0LmNvbS9DUFMwfAYIKwYBBQUHAQEEcDBuMCQGCCsGAQUFBzABhhho dHRwOi8vb2NzcC5kaWdpY2VydC5jb20wRgYIKwYBBQUHMAKGOmh0dHA6Ly9jYWNl cnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJTZWN1cmVTZXJ2ZXJDQS5jcnQw DAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAQEAvcTWenNuvvrhX2omm8LQ zWOuu8jqpoflACwD4lOSZ4TgOe4pQGCjXq8aRBD5k+goqQrPVf9lHnelUHFQac0Q 5WT4YUmisUbF0S4uY5OGQymM52MvUWG4ODL4gaWhFvN+HAXrDPP/9iitsjV0QOnl CDq7Q4/XYRYW3opu5nLLbfW6v4QvF5yzZagEACGs7Vt32p6l391UcU8f6wiB3uMD eioCvjpv/+2YOUNlDPCM3uBubjUhHOwO817wBxXkzdk1OSRe4jzcw/uX6wL7birt fbaSkpilvVX529pSzB2Lvi9xWOoGMM578dpQ0h3PwhmmvKhhCWP+pI05k3oSkYCP ng== -----END CERTIFICATE----- END_OF_JCLOUDS_FILE cat > /etc/chef/client.rb <<-'END_OF_JCLOUDS_FILE' require 'rubygems' require 'ohai' o = Ohai::System.new o.all_plugins node_name "foo-" + o[:ipaddress] log_level :info log_location STDOUT validation_client_name "chef-validator" chef_server_url "http://localhost:4000" ssl_ca_file "/etc/chef/chef-server.crt" ssl_ca_path "/etc/chef" ssl_verify_mode :verify_peer verify_api_cert true END_OF_JCLOUDS_FILE cat > /etc/chef/validation.pem <<-'END_OF_JCLOUDS_FILE' -----BEGIN PRIVATE KEY----- LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVB eWIyWkpKcUdtMEtLUis4bmZRSk5zU2QrRjl0WE5NVjdDZk9jVzZqc3FzOEVaZ2lW ClIwOWhEMUlZT2o0WXFNMHFKT05sZ3lnNHhSV2V3ZFNHN1FUUGoxbEpwVkFpZGE5 c1h5MitrenlhZ1pBMUFtME8KWmNicWI1aG9lSURnY1grZURhNzlzMHUwRG9tamNm TzlFS2h2SExCeit6TSszUXFQUmtQVjhuWVRiZnMrSGpWegp6T1U2RDFCMFhSMytJ UFpabDJBbldzMmQwcWhuU3RIY0RVdm5SVlEwUDQ4Mll3TjlWZ2NlT1p0cFB6MERD S0VKCjVUeDVTVHViOGswL3p0L1ZBTUhRYWZMU3VRTUxkMnM0Wkx1T1pwdE4vL3VB c1RteGlyZXFkMzd6KzhaVGRCYkoKOExFcEoraUNYdVNmbTVhVWg3aXc2b3h2VG9Z MkFMNTMraksyVVFJREFRQUJBb0lCQVFEQTg4QjNpL3hXbjB2WApCVnhGYW1DWW9l Y3VOakd3WFhrU3laZXc2MTZBK0VPQ3U0N2JoNGFUdXJkRmJZTDBZRmFBdGFXdnps YU4yZUhnCkRiK0hEdVRlZkUyOStXa2NHazZTc2hQbWl6NVQwWE9DQUlDV3c2d1NW RGtIbUd3UzRqWnZiQUZtN1c4bndHazkKWWh4Z3hGaVJuZ3N3SlpGb3BPTG9GNVdY czJ0ZDhndUlZTnNsTXBvN3R1NTBpRm5CSHdLTzJac1BBazh0OW5uUwp4bERhdkty dXltRW1xSENyMytkdGlvNWVhZW5KY3AzZmpvWEJRT0tVazNpcElJMjlYUkI4TnFl Q1ZWLzdLeHdxCmNrcU9CRWJSd0JjbGNreUliRCtSaUFnS3ZPZWxPUmpFaUU5UjQy dnVxdnhSQTZrOWtkOW83dXRsWDBBVXRwRW4KM2daYzZMZXBBb0dCQVA5YWVsNVk3 NStzSzJKSlVOT09oTzhhZTQ1Y2RzaWxwMnlJMFgrVUJhU3VRczIrZHlQcAprcEVI QXhkNHBtbVN2bi84YzlUbEVaaHIrcVliQUJYVlBsRG5jeHBJdXcyQWpiazdzL1M0 WGFTS3NScXBYTDU3CnpqL1FPcUxrUms4K09WVjlxNmxNZVFOcUx0RWoxdTZKUHZp WDcwUm8rRlF0UnR0Tk9ZYmZkUC9mQW9HQkFNcEEKWGpSNXdvVjVzVWIrUkVnOXZF dVlvOFJTeU9hcnhxS0ZDSVhWVU5zTE94KzIyK0FLNCtDUXBidWVXTjdqb3RybApZ RDZ1VDZzdldpM0FBQzdraVkwVUkvZmpWUFJDVWk4dFZvUVVFMFRhVTVWTElUYVlP QitXL2JCYURFNE05NTYwCjFOdURXTzkwYmFBNWRmVTQ0aXV6dmEwMnJHSlhLOStu UzNvOG5rL1BBb0dCQUxPTDZkam5EZTRtd0FhRzZKY28KY2Q0eHI4amt5UHpDUlp1 eUJDU0Jid3BoSVVYTGM3aERwclBreTA2NG5jSkQxVURtd0lka1hkL2ZwTWtnMlFt QQovQ1VrNkxFRmpNaXNxSG9qT2FDTDlnUVpKUGhMTjVRVU4yeDFQSldHanMxdlFo OFRreDBpVVVDT2E4YlFQWE5SCiszNE9Uc1c2VFVuYTRDU1pBeWNMZmhmZkFvR0JB SWdnVnNlZkJDdnVRa0YwTmVVaG1EQ1JaZmhuZDh5NTVSSFIKMUhDdnFLSWxwdity aGNYL3pteUJMdXRlb3BZeVJKUnNPaUUyRlcwMGk4K3JJUFJ1NFozUTVueWJ4N3cz UHpWOQpvSE41UjViYUU5T3lJNEtwWld6dHBZWWl0WkY2N05jbkF2VlVMSEhPdlZK UUduS1lmTEhKWW1ySkY3R0Exb2pNCkF1TWRGYmpGQW9HQVB4VWh4d0Z5OGdhcUJh aEtVRVpuNEY4MUhGUDVpaEdoa1Q0UUw2QUZQTzJlK0poSUdqdVIKMjcrODVoY0Zx UStISFZ0RnNtODFiL2ErUjdQNFV1Q1JnYzhlQ2p4UU1vSjFYbDRuN1ZialBiSE1u SU4wUnl2ZApPNFpwV0RXWW5DTzAyMUpUT1VVT0o0Si95MDQxNkJ2a3cwejU5eTdz Tlg3d0RCQkhIYksvWENjPQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo= -----END PRIVATE KEY----- END_OF_JCLOUDS_FILE cat > /etc/chef/first-boot.json <<-'END_OF_JCLOUDS_FILE' {"tomcat6":{"ssl_port":8433},"run_list":["recipe[apache2]","role[webserver]"]} END_OF_JCLOUDS_FILE chef-client -j /etc/chef/first-boot.json ================================================ FILE: apis/chef/src/test/resources/bootstrap.sh ================================================ mkdir -p /etc/chef cat > /etc/chef/client.rb <<-'END_OF_JCLOUDS_FILE' require 'rubygems' require 'ohai' o = Ohai::System.new o.all_plugins node_name "foo-" + o[:ipaddress] log_level :info log_location STDOUT validation_client_name "chef-validator" chef_server_url "http://localhost:4000" END_OF_JCLOUDS_FILE cat > /etc/chef/validation.pem <<-'END_OF_JCLOUDS_FILE' -----BEGIN PRIVATE KEY----- LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVB eWIyWkpKcUdtMEtLUis4bmZRSk5zU2QrRjl0WE5NVjdDZk9jVzZqc3FzOEVaZ2lW ClIwOWhEMUlZT2o0WXFNMHFKT05sZ3lnNHhSV2V3ZFNHN1FUUGoxbEpwVkFpZGE5 c1h5MitrenlhZ1pBMUFtME8KWmNicWI1aG9lSURnY1grZURhNzlzMHUwRG9tamNm TzlFS2h2SExCeit6TSszUXFQUmtQVjhuWVRiZnMrSGpWegp6T1U2RDFCMFhSMytJ UFpabDJBbldzMmQwcWhuU3RIY0RVdm5SVlEwUDQ4Mll3TjlWZ2NlT1p0cFB6MERD S0VKCjVUeDVTVHViOGswL3p0L1ZBTUhRYWZMU3VRTUxkMnM0Wkx1T1pwdE4vL3VB c1RteGlyZXFkMzd6KzhaVGRCYkoKOExFcEoraUNYdVNmbTVhVWg3aXc2b3h2VG9Z MkFMNTMraksyVVFJREFRQUJBb0lCQVFEQTg4QjNpL3hXbjB2WApCVnhGYW1DWW9l Y3VOakd3WFhrU3laZXc2MTZBK0VPQ3U0N2JoNGFUdXJkRmJZTDBZRmFBdGFXdnps YU4yZUhnCkRiK0hEdVRlZkUyOStXa2NHazZTc2hQbWl6NVQwWE9DQUlDV3c2d1NW RGtIbUd3UzRqWnZiQUZtN1c4bndHazkKWWh4Z3hGaVJuZ3N3SlpGb3BPTG9GNVdY czJ0ZDhndUlZTnNsTXBvN3R1NTBpRm5CSHdLTzJac1BBazh0OW5uUwp4bERhdkty dXltRW1xSENyMytkdGlvNWVhZW5KY3AzZmpvWEJRT0tVazNpcElJMjlYUkI4TnFl Q1ZWLzdLeHdxCmNrcU9CRWJSd0JjbGNreUliRCtSaUFnS3ZPZWxPUmpFaUU5UjQy dnVxdnhSQTZrOWtkOW83dXRsWDBBVXRwRW4KM2daYzZMZXBBb0dCQVA5YWVsNVk3 NStzSzJKSlVOT09oTzhhZTQ1Y2RzaWxwMnlJMFgrVUJhU3VRczIrZHlQcAprcEVI QXhkNHBtbVN2bi84YzlUbEVaaHIrcVliQUJYVlBsRG5jeHBJdXcyQWpiazdzL1M0 WGFTS3NScXBYTDU3CnpqL1FPcUxrUms4K09WVjlxNmxNZVFOcUx0RWoxdTZKUHZp WDcwUm8rRlF0UnR0Tk9ZYmZkUC9mQW9HQkFNcEEKWGpSNXdvVjVzVWIrUkVnOXZF dVlvOFJTeU9hcnhxS0ZDSVhWVU5zTE94KzIyK0FLNCtDUXBidWVXTjdqb3RybApZ RDZ1VDZzdldpM0FBQzdraVkwVUkvZmpWUFJDVWk4dFZvUVVFMFRhVTVWTElUYVlP QitXL2JCYURFNE05NTYwCjFOdURXTzkwYmFBNWRmVTQ0aXV6dmEwMnJHSlhLOStu UzNvOG5rL1BBb0dCQUxPTDZkam5EZTRtd0FhRzZKY28KY2Q0eHI4amt5UHpDUlp1 eUJDU0Jid3BoSVVYTGM3aERwclBreTA2NG5jSkQxVURtd0lka1hkL2ZwTWtnMlFt QQovQ1VrNkxFRmpNaXNxSG9qT2FDTDlnUVpKUGhMTjVRVU4yeDFQSldHanMxdlFo OFRreDBpVVVDT2E4YlFQWE5SCiszNE9Uc1c2VFVuYTRDU1pBeWNMZmhmZkFvR0JB SWdnVnNlZkJDdnVRa0YwTmVVaG1EQ1JaZmhuZDh5NTVSSFIKMUhDdnFLSWxwdity aGNYL3pteUJMdXRlb3BZeVJKUnNPaUUyRlcwMGk4K3JJUFJ1NFozUTVueWJ4N3cz UHpWOQpvSE41UjViYUU5T3lJNEtwWld6dHBZWWl0WkY2N05jbkF2VlVMSEhPdlZK UUduS1lmTEhKWW1ySkY3R0Exb2pNCkF1TWRGYmpGQW9HQVB4VWh4d0Z5OGdhcUJh aEtVRVpuNEY4MUhGUDVpaEdoa1Q0UUw2QUZQTzJlK0poSUdqdVIKMjcrODVoY0Zx UStISFZ0RnNtODFiL2ErUjdQNFV1Q1JnYzhlQ2p4UU1vSjFYbDRuN1ZialBiSE1u SU4wUnl2ZApPNFpwV0RXWW5DTzAyMUpUT1VVT0o0Si95MDQxNkJ2a3cwejU5eTdz Tlg3d0RCQkhIYksvWENjPQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo= -----END PRIVATE KEY----- END_OF_JCLOUDS_FILE cat > /etc/chef/first-boot.json <<-'END_OF_JCLOUDS_FILE' {"tomcat6":{"ssl_port":8433},"run_list":["recipe[apache2]","role[webserver]"]} END_OF_JCLOUDS_FILE chef-client -j /etc/chef/first-boot.json ================================================ FILE: apis/chef/src/test/resources/brew-cookbook.json ================================================ { "attributes" : [ ], "chef_type" : "cookbook_version", "cookbook_name" : "brew", "definitions" : [ ], "files" : [ ], "json_class" : "Chef::CookbookVersion", "libraries" : [ ], "metadata" : { "attributes" : { }, "conflicting" : { }, "dependencies" : { }, "description" : "A fabulous new cookbook", "groupings" : { }, "license" : "Apache v2.0", "long_description" : "", "maintainer" : "Your Name", "maintainer_email" : "youremail@example.com", "name" : "brew", "platforms" : { }, "providing" : { "brew" : "0.0.0" }, "recipes" : { "brew" : "" }, "recommendations" : { }, "replacing" : { }, "suggestions" : { }, "version" : "0.0.0" }, "name" : "brew-0.0.0", "providers" : [ { "checksum" : "0c5ecd7788cf4f6c7de2a57193897a6c", "name" : "brew.rb", "path" : "providers/brew.rb", "specificity" : "default", "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-0c5ecd7788cf4f6c7de2a57193897a6c?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774465&Signature=brTA3YkBF7iDnjPGCCHxgm7AHko%3D" } ], "recipes" : [ { "checksum" : "1dda05ed139664f1f89b9dec482b77c0", "name" : "default.rb", "path" : "recipes/default.rb", "specificity" : "default", "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-1dda05ed139664f1f89b9dec482b77c0?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774465&Signature=dOzPk64at92zOfZlxt1suDpGuPs%3D" } ], "resources" : [ { "checksum" : "0189e76ccc476701d6b374e5a1a27347", "name" : "brew.rb", "path" : "resources/brew.rb", "specificity" : "default", "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-0189e76ccc476701d6b374e5a1a27347?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774465&Signature=ufrI1k6pKJ1%2FBRMAaIGr6icJlpc%3D" } ], "root_files" : [ ], "templates" : [ ], "version" : "0.0.0" } ================================================ FILE: apis/chef/src/test/resources/chef.crt ================================================ -----BEGIN CERTIFICATE----- MIIFDTCCA/WgAwIBAgIQBZ8R1sZP2Lbc8x554UUQ2DANBgkqhkiG9w0BAQsFADBN MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMScwJQYDVQQDEx5E aWdpQ2VydCBTSEEyIFNlY3VyZSBTZXJ2ZXIgQ0EwHhcNMTQxMTEwMDAwMDAwWhcN MTcxMTE0MTIwMDAwWjBlMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv bjEQMA4GA1UEBxMHU2VhdHRsZTEbMBkGA1UEChMSQ2hlZiBTb2Z0d2FyZSwgSW5j MRIwEAYDVQQDDAkqLmNoZWYuaW8wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK AoIBAQC3xCIczkV10O5jTDpbd4YlPLC6kfnVoOkno2N/OOlcLQu3ulj/Lj1j4r6e 2XthJLcFgTO+y+1/IKnnpLKDfkx1YngWEBXEBP+MrrpDUKKs053s45/bI9QBPISA tXgnYxMH9Glo6FWWd13TUq++OKGw1p1wazH64XK4MAf5y/lkmWXIWumNuO35ZqtB ME3wJISwVHzHB2CQjlDklt+Mb0APEiIFIZflgu9JNBYzLdvUtxiz15FUZQI7SsYL TfXOD1KBNMWqN8snG2e5gRAzB2D161DFvAZt8OiYUe+3QurNlTYVzeHv1ok6UqgM ZcLzg8m801rRip0D7FCGvMCU/ktdAgMBAAGjggHPMIIByzAfBgNVHSMEGDAWgBQP gGEcgjFh1S8o541GOLQs4cbZ4jAdBgNVHQ4EFgQUwldjw4Pb4HV+wxGZ7MSSRh+d pm4wHQYDVR0RBBYwFIIJKi5jaGVmLmlvggdjaGVmLmlvMA4GA1UdDwEB/wQEAwIF oDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwawYDVR0fBGQwYjAvoC2g K4YpaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NzY2Etc2hhMi1nMy5jcmwwL6At oCuGKWh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9zc2NhLXNoYTItZzMuY3JsMEIG A1UdIAQ7MDkwNwYJYIZIAYb9bAEBMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3 LmRpZ2ljZXJ0LmNvbS9DUFMwfAYIKwYBBQUHAQEEcDBuMCQGCCsGAQUFBzABhhho dHRwOi8vb2NzcC5kaWdpY2VydC5jb20wRgYIKwYBBQUHMAKGOmh0dHA6Ly9jYWNl cnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJTZWN1cmVTZXJ2ZXJDQS5jcnQw DAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQsFAAOCAQEAvcTWenNuvvrhX2omm8LQ zWOuu8jqpoflACwD4lOSZ4TgOe4pQGCjXq8aRBD5k+goqQrPVf9lHnelUHFQac0Q 5WT4YUmisUbF0S4uY5OGQymM52MvUWG4ODL4gaWhFvN+HAXrDPP/9iitsjV0QOnl CDq7Q4/XYRYW3opu5nLLbfW6v4QvF5yzZagEACGs7Vt32p6l391UcU8f6wiB3uMD eioCvjpv/+2YOUNlDPCM3uBubjUhHOwO817wBxXkzdk1OSRe4jzcw/uX6wL7birt fbaSkpilvVX529pSzB2Lvi9xWOoGMM578dpQ0h3PwhmmvKhhCWP+pI05k3oSkYCP ng== -----END CERTIFICATE----- ================================================ FILE: apis/chef/src/test/resources/client-no-pub-key.json ================================================ { "certificate" : "-----BEGIN CERTIFICATE-----\nMIIClzCCAgCgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBnjELMAkGA1UEBhMCVVMx\nEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFjAUBgNVBAoM\nDU9wc2NvZGUsIEluYy4xHDAaBgNVBAsME0NlcnRpZmljYXRlIFNlcnZpY2UxMjAw\nBgNVBAMMKW9wc2NvZGUuY29tL2VtYWlsQWRkcmVzcz1hdXRoQG9wc2NvZGUuY29t\nMB4XDTEwMDczMDIwNDEzMFoXDTIwMDcyNzIwNDEzMFowADCCASIwDQYJKoZIhvcN\nAQEBBQADggEPADCCAQoCggEBAMm9mSSahptCikfvJ30CTbEnfhfbVzTFewnznFuo\n7KrPBGYIlUdPYQ9SGDo+GKjNKiTjZYMoOMUVnsHUhu0Ez49ZSaVQInWvbF8tvpM8\nmoGQNQJtDmXG6m+YaHiA4HF/ng2u/bNLtA6Jo3HzvRCobxywc/szPt0Kj0ZD1fJ2\nE237Ph41c8zlOg9QdF0d/iD2WZdgJ1rNndKoZ0rR3A1L50VUND+PNmMDfVYHHjmb\naT89AwihCeU8eUk7m/JNP87f1QDB0Gny0rkDC3drOGS7jmabTf/7gLE5sYq3qnd+\n8/vGU3QWyfCxKSfogl7kn5uWlIe4sOqMb06GNgC+d/oytlECAwEAATANBgkqhkiG\n9w0BAQUFAAOBgQBftzSZxstWw60GqRTDNN/F2GnrdtnKBoXzHww3r6jtGEylYq20\n5KfKpEx+sPX0gyZuYJiXC2CkEjImAluWKcdN9ZF6VD541sheAjbiaU7q7ZsztTxF\nWUH2tCvHeDXYKPKek3QzL7bYpUhLnCN/XxEv6ibeMDwtI7f5qpk2Aspzcw==\n-----END CERTIFICATE-----\n", "clientname" : "adriancole-jcloudstest", "name" : "adriancole-jcloudstest", "orgname" : "jclouds", "private_key" : "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEAyb2ZJJqGm0KKR+8nfQJNsSd+F9tXNMV7CfOcW6jsqs8EZgiV\nR09hD1IYOj4YqM0qJONlgyg4xRWewdSG7QTPj1lJpVAida9sXy2+kzyagZA1Am0O\nZcbqb5hoeIDgcX+eDa79s0u0DomjcfO9EKhvHLBz+zM+3QqPRkPV8nYTbfs+HjVz\nzOU6D1B0XR3+IPZZl2AnWs2d0qhnStHcDUvnRVQ0P482YwN9VgceOZtpPz0DCKEJ\n5Tx5STub8k0/zt/VAMHQafLSuQMLd2s4ZLuOZptN//uAsTmxireqd37z+8ZTdBbJ\n8LEpJ+iCXuSfm5aUh7iw6oxvToY2AL53+jK2UQIDAQABAoIBAQDA88B3i/xWn0vX\nBVxFamCYoecuNjGwXXkSyZew616A+EOCu47bh4aTurdFbYL0YFaAtaWvzlaN2eHg\nDb+HDuTefE29+WkcGk6SshPmiz5T0XOCAICWw6wSVDkHmGwS4jZvbAFm7W8nwGk9\nYhxgxFiRngswJZFopOLoF5WXs2td8guIYNslMpo7tu50iFnBHwKO2ZsPAk8t9nnS\nxlDavKruymEmqHCr3+dtio5eaenJcp3fjoXBQOKUk3ipII29XRB8NqeCVV/7Kxwq\nckqOBEbRwBclckyIbD+RiAgKvOelORjEiE9R42vuqvxRA6k9kd9o7utlX0AUtpEn\n3gZc6LepAoGBAP9ael5Y75+sK2JJUNOOhO8ae45cdsilp2yI0X+UBaSuQs2+dyPp\nkpEHAxd4pmmSvn/8c9TlEZhr+qYbABXVPlDncxpIuw2Ajbk7s/S4XaSKsRqpXL57\nzj/QOqLkRk8+OVV9q6lMeQNqLtEj1u6JPviX70Ro+FQtRttNOYbfdP/fAoGBAMpA\nXjR5woV5sUb+REg9vEuYo8RSyOarxqKFCIXVUNsLOx+22+AK4+CQpbueWN7jotrl\nYD6uT6svWi3AAC7kiY0UI/fjVPRCUi8tVoQUE0TaU5VLITaYOB+W/bBaDE4M9560\n1NuDWO90baA5dfU44iuzva02rGJXK9+nS3o8nk/PAoGBALOL6djnDe4mwAaG6Jco\ncd4xr8jkyPzCRZuyBCSBbwphIUXLc7hDprPky064ncJD1UDmwIdkXd/fpMkg2QmA\n/CUk6LEFjMisqHojOaCL9gQZJPhLN5QUN2x1PJWGjs1vQh8Tkx0iUUCOa8bQPXNR\n+34OTsW6TUna4CSZAycLfhffAoGBAIggVsefBCvuQkF0NeUhmDCRZfhnd8y55RHR\n1HCvqKIlpv+rhcX/zmyBLuteopYyRJRsOiE2FW00i8+rIPRu4Z3Q5nybx7w3PzV9\noHN5R5baE9OyI4KpZWztpYYitZF67NcnAvVULHHOvVJQGnKYfLHJYmrJF7GA1ojM\nAuMdFbjFAoGAPxUhxwFy8gaqBahKUEZn4F81HFP5ihGhkT4QL6AFPO2e+JhIGjuR\n27+85hcFqQ+HHVtFsm81b/a+R7P4UuCRgc8eCjxQMoJ1Xl4n7VbjPbHMnIN0Ryvd\nO4ZpWDWYnCO021JTOUUOJ4J/y0416Bvkw0z59y7sNX7wDBBHHbK/XCc=\n-----END RSA PRIVATE KEY-----\n", "uri" : "https://api.opscode.com/organizations/jclouds/clients/adriancole-jcloudstest", "validator" : false } ================================================ FILE: apis/chef/src/test/resources/client.json ================================================ { "certificate" : "-----BEGIN CERTIFICATE-----\nMIIClzCCAgCgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBnjELMAkGA1UEBhMCVVMx\nEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFjAUBgNVBAoM\nDU9wc2NvZGUsIEluYy4xHDAaBgNVBAsME0NlcnRpZmljYXRlIFNlcnZpY2UxMjAw\nBgNVBAMMKW9wc2NvZGUuY29tL2VtYWlsQWRkcmVzcz1hdXRoQG9wc2NvZGUuY29t\nMB4XDTEwMDczMDIwNDEzMFoXDTIwMDcyNzIwNDEzMFowADCCASIwDQYJKoZIhvcN\nAQEBBQADggEPADCCAQoCggEBAMm9mSSahptCikfvJ30CTbEnfhfbVzTFewnznFuo\n7KrPBGYIlUdPYQ9SGDo+GKjNKiTjZYMoOMUVnsHUhu0Ez49ZSaVQInWvbF8tvpM8\nmoGQNQJtDmXG6m+YaHiA4HF/ng2u/bNLtA6Jo3HzvRCobxywc/szPt0Kj0ZD1fJ2\nE237Ph41c8zlOg9QdF0d/iD2WZdgJ1rNndKoZ0rR3A1L50VUND+PNmMDfVYHHjmb\naT89AwihCeU8eUk7m/JNP87f1QDB0Gny0rkDC3drOGS7jmabTf/7gLE5sYq3qnd+\n8/vGU3QWyfCxKSfogl7kn5uWlIe4sOqMb06GNgC+d/oytlECAwEAATANBgkqhkiG\n9w0BAQUFAAOBgQBftzSZxstWw60GqRTDNN/F2GnrdtnKBoXzHww3r6jtGEylYq20\n5KfKpEx+sPX0gyZuYJiXC2CkEjImAluWKcdN9ZF6VD541sheAjbiaU7q7ZsztTxF\nWUH2tCvHeDXYKPKek3QzL7bYpUhLnCN/XxEv6ibeMDwtI7f5qpk2Aspzcw==\n-----END CERTIFICATE-----\n", "clientname" : "adriancole-jcloudstest", "name" : "adriancole-jcloudstest", "orgname" : "jclouds", "private_key" : "-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEAyb2ZJJqGm0KKR+8nfQJNsSd+F9tXNMV7CfOcW6jsqs8EZgiV\nR09hD1IYOj4YqM0qJONlgyg4xRWewdSG7QTPj1lJpVAida9sXy2+kzyagZA1Am0O\nZcbqb5hoeIDgcX+eDa79s0u0DomjcfO9EKhvHLBz+zM+3QqPRkPV8nYTbfs+HjVz\nzOU6D1B0XR3+IPZZl2AnWs2d0qhnStHcDUvnRVQ0P482YwN9VgceOZtpPz0DCKEJ\n5Tx5STub8k0/zt/VAMHQafLSuQMLd2s4ZLuOZptN//uAsTmxireqd37z+8ZTdBbJ\n8LEpJ+iCXuSfm5aUh7iw6oxvToY2AL53+jK2UQIDAQABAoIBAQDA88B3i/xWn0vX\nBVxFamCYoecuNjGwXXkSyZew616A+EOCu47bh4aTurdFbYL0YFaAtaWvzlaN2eHg\nDb+HDuTefE29+WkcGk6SshPmiz5T0XOCAICWw6wSVDkHmGwS4jZvbAFm7W8nwGk9\nYhxgxFiRngswJZFopOLoF5WXs2td8guIYNslMpo7tu50iFnBHwKO2ZsPAk8t9nnS\nxlDavKruymEmqHCr3+dtio5eaenJcp3fjoXBQOKUk3ipII29XRB8NqeCVV/7Kxwq\nckqOBEbRwBclckyIbD+RiAgKvOelORjEiE9R42vuqvxRA6k9kd9o7utlX0AUtpEn\n3gZc6LepAoGBAP9ael5Y75+sK2JJUNOOhO8ae45cdsilp2yI0X+UBaSuQs2+dyPp\nkpEHAxd4pmmSvn/8c9TlEZhr+qYbABXVPlDncxpIuw2Ajbk7s/S4XaSKsRqpXL57\nzj/QOqLkRk8+OVV9q6lMeQNqLtEj1u6JPviX70Ro+FQtRttNOYbfdP/fAoGBAMpA\nXjR5woV5sUb+REg9vEuYo8RSyOarxqKFCIXVUNsLOx+22+AK4+CQpbueWN7jotrl\nYD6uT6svWi3AAC7kiY0UI/fjVPRCUi8tVoQUE0TaU5VLITaYOB+W/bBaDE4M9560\n1NuDWO90baA5dfU44iuzva02rGJXK9+nS3o8nk/PAoGBALOL6djnDe4mwAaG6Jco\ncd4xr8jkyPzCRZuyBCSBbwphIUXLc7hDprPky064ncJD1UDmwIdkXd/fpMkg2QmA\n/CUk6LEFjMisqHojOaCL9gQZJPhLN5QUN2x1PJWGjs1vQh8Tkx0iUUCOa8bQPXNR\n+34OTsW6TUna4CSZAycLfhffAoGBAIggVsefBCvuQkF0NeUhmDCRZfhnd8y55RHR\n1HCvqKIlpv+rhcX/zmyBLuteopYyRJRsOiE2FW00i8+rIPRu4Z3Q5nybx7w3PzV9\noHN5R5baE9OyI4KpZWztpYYitZF67NcnAvVULHHOvVJQGnKYfLHJYmrJF7GA1ojM\nAuMdFbjFAoGAPxUhxwFy8gaqBahKUEZn4F81HFP5ihGhkT4QL6AFPO2e+JhIGjuR\n27+85hcFqQ+HHVtFsm81b/a+R7P4UuCRgc8eCjxQMoJ1Xl4n7VbjPbHMnIN0Ryvd\nO4ZpWDWYnCO021JTOUUOJ4J/y0416Bvkw0z59y7sNX7wDBBHHbK/XCc=\n-----END RSA PRIVATE KEY-----\n", "uri" : "https://api.opscode.com/organizations/jclouds/clients/adriancole-jcloudstest", "validator" : false, "public_key" : "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyb2ZJJqGm0KKR+8nfQJN\nsSd+F9tXNMV7CfOcW6jsqs8EZgiVR09hD1IYOj4YqM0qJONlgyg4xRWewdSG7QTP\nj1lJpVAida9sXy2+kzyagZA1Am0OZcbqb5hoeIDgcX+eDa79s0u0DomjcfO9EKhv\nHLBz+zM+3QqPRkPV8nYTbfs+HjVzzOU6D1B0XR3+IPZZl2AnWs2d0qhnStHcDUvn\nRVQ0P482YwN9VgceOZtpPz0DCKEJ5Tx5STub8k0/zt/VAMHQafLSuQMLd2s4ZLuO\nZptN//uAsTmxireqd37z+8ZTdBbJ8LEpJ+iCXuSfm5aUh7iw6oxvToY2AL53+jK2\nUQIDAQAB\n-----END PUBLIC KEY-----\n" } ================================================ FILE: apis/chef/src/test/resources/clients_list.json ================================================ { "chef-webui": "http://localhost:4000/clients/chef-webui", "chef-validator": "http://localhost:4000/clients/chef-validator", "adam": "http://localhost:4000/clients/adam" } ================================================ FILE: apis/chef/src/test/resources/data_list.json ================================================ { "users": "http://localhost:4000/data/users", "applications": "http://localhost:4000/data/applications" } ================================================ FILE: apis/chef/src/test/resources/env_cookbooks.json ================================================ { "apache2" => { "url" => "http://localhost:4000/cookbooks/apache2", "versions" => [ {"url" => "http://localhost:4000/cookbooks/apache2/5.1.0", "version" => "5.1.0"}, {"url" => "http://localhost:4000/cookbooks/apache2/4.2.0", "version" => "4.2.0"} ] }, "nginx" => { "url" => "http://localhost:4000/cookbooks/nginx", "versions" => [ {"url" => "http://localhost:4000/cookbooks/nginx/1.0.0", "version" => "1.0.0"}, {"url" => "http://localhost:4000/cookbooks/nginx/0.3.0", "version" => "0.3.0"} ] } } ================================================ FILE: apis/chef/src/test/resources/environment_recipes.json ================================================ [ "ant", "apache2", "apache2::mod_auth_openid" ] ================================================ FILE: apis/chef/src/test/resources/group-update.json ================================================ {"groupname":"admins","actors":{"clients":["abiquo"],"groups":["admins"],"users":["nacx"]}} ================================================ FILE: apis/chef/src/test/resources/group.json ================================================ { "actors" : [ "abiquo", "nacx", "pivotal" ], "clients" : [ "abiquo" ], "groupname" : "admins", "groups" : [ "billing-admins" ], "name" : "admins", "orgname" : "nacx", "users" : [ "nacx", "pivotal" ] } ================================================ FILE: apis/chef/src/test/resources/groups.json ================================================ { "965f2db33d302ed4625d172e0bc36920" : "https://api.opscode.com/organizations/nacx/groups/965f2db33d302ed4625d172e0bc36920", "admins" : "https://api.opscode.com/organizations/nacx/groups/admins", "billing-admins" : "https://api.opscode.com/organizations/nacx/groups/billing-admins", "clients" : "https://api.opscode.com/organizations/nacx/groups/clients", "users" : "https://api.opscode.com/organizations/nacx/groups/users" } ================================================ FILE: apis/chef/src/test/resources/logback.xml ================================================ target/test-data/jclouds.log %d %-5p [%c] [%thread] %m%n target/test-data/jclouds-wire.log %d %-5p [%c] [%thread] %m%n ================================================ FILE: apis/chef/src/test/resources/mysql-cookbook.json ================================================ { "attributes" : [ { "checksum" : "548fa4bc548b8b59ac98fffee8e81f4a", "name" : "server.rb", "path" : "attributes/server.rb", "specificity" : "default", "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-548fa4bc548b8b59ac98fffee8e81f4a?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=MsgggSKS0T1q1Lc72nJpHORBQX0%3D" } ], "chef_type" : "cookbook_version", "cookbook_name" : "mysql", "definitions" : [ ], "files" : [ ], "json_class" : "Chef::CookbookVersion", "libraries" : [ { "checksum" : "b2eb0760c07734be9c637dcffc86175a", "name" : "database.rb", "path" : "libraries/database.rb", "specificity" : "default", "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-b2eb0760c07734be9c637dcffc86175a?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=CvVbxzrA%2Fuxc59ZjLR5BsMozfxk%3D" } ], "metadata" : { "attributes" : { "mysql/bind_address" : { "calculated" : false, "choice" : [ ], "default" : "ipaddress", "description" : "Address that mysqld should listen on", "display_name" : "MySQL Bind Address", "recipes" : [ ], "required" : "optional", "type" : "string" }, "mysql/datadir" : { "calculated" : false, "choice" : [ ], "default" : "/var/lib/mysql", "description" : "Location of mysql databases", "display_name" : "MySQL Data Directory", "recipes" : [ ], "required" : "optional", "type" : "string" }, "mysql/ec2_path" : { "calculated" : false, "choice" : [ ], "default" : "/mnt/mysql", "description" : "Location of mysql directory on EC2 instance EBS volumes", "display_name" : "MySQL EC2 Path", "recipes" : [ ], "required" : "optional", "type" : "string" }, "mysql/server_root_password" : { "calculated" : false, "choice" : [ ], "default" : "randomly generated", "description" : "Randomly generated password for the mysqld root user", "display_name" : "MySQL Server Root Password", "recipes" : [ ], "required" : "optional", "type" : "string" }, "mysql/tunable" : { "calculated" : false, "choice" : [ ], "description" : "Hash of MySQL tunable attributes", "display_name" : "MySQL Tunables", "recipes" : [ ], "required" : "optional", "type" : "hash" }, "mysql/tunable/back_log" : { "calculated" : false, "choice" : [ ], "default" : "128", "display_name" : "MySQL Tunable Back Log", "recipes" : [ ], "required" : "optional", "type" : "string" }, "mysql/tunable/key_buffer" : { "calculated" : false, "choice" : [ ], "default" : "250M", "display_name" : "MySQL Tuntable Key Buffer", "recipes" : [ ], "required" : "optional", "type" : "string" }, "mysql/tunable/max_connections" : { "calculated" : false, "choice" : [ ], "default" : "800", "display_name" : "MySQL Tunable Max Connections", "recipes" : [ ], "required" : "optional", "type" : "string" }, "mysql/tunable/max_heap_table_size" : { "calculated" : false, "choice" : [ ], "default" : "32M", "display_name" : "MySQL Tunable Max Heap Table Size", "recipes" : [ ], "required" : "optional", "type" : "string" }, "mysql/tunable/net_read_timeout" : { "calculated" : false, "choice" : [ ], "default" : "30", "display_name" : "MySQL Tunable Net Read Timeout", "recipes" : [ ], "required" : "optional", "type" : "string" }, "mysql/tunable/net_write_timeout" : { "calculated" : false, "choice" : [ ], "default" : "30", "display_name" : "MySQL Tunable Net Write Timeout", "recipes" : [ ], "required" : "optional", "type" : "string" }, "mysql/tunable/table_cache" : { "calculated" : false, "choice" : [ ], "default" : "128", "display_name" : "MySQL Tunable Table Cache", "recipes" : [ ], "required" : "optional", "type" : "string" }, "mysql/tunable/wait_timeout" : { "calculated" : false, "choice" : [ ], "default" : "180", "display_name" : "MySQL Tunable Wait Timeout", "recipes" : [ ], "required" : "optional", "type" : "string" } }, "conflicting" : { }, "dependencies" : { "openssl" : "" }, "description" : "Installs and configures mysql for client or server", "groupings" : { }, "license" : "Apache 2.0", "long_description" : "= DESCRIPTION:\n\nInstalls and configures MySQL client or server.\n\n= REQUIREMENTS:\n\n== Platform:\n\nBest tested on Ubuntu 9.04,9.10. On EC2, requires platform that supports -o bind option for the 'mount' command.\n\n== Cookbooks:\n\nRequires Opscode's openssl cookbook for secure password generation.\n\n= ATTRIBUTES: \n\n* mysql[:server_root_password] - Set the server's root password with this, default is a randomly generated password with OpenSSL::Random.random_bytes.\n* mysql[:server_repl_password] - Set the replication user 'repl' password with this, default is a randomly generated password with OpenSSL::Random.random_bytes.\n* mysql[:server_debian_password] - Set the debian-sys-maint user password with this, default is a randomly generated password with OpenSSL::Random.random_bytes.\n* mysql[:bind_address] - Listen address for MySQLd, default is node's ipaddress.\n* mysql[:datadir] - Location for mysql data directory, default is \"/var/lib/mysql\" \n* mysql[:ec2_path] - location of mysql datadir on EC2 nodes, default \"/mnt/mysql\" \n\nPerformance tuning attributes, each corresponds to the same-named parameter in my.cnf; default values listed\n\n* mysql[:tunable][:key_buffer] = \"250M\"\n* mysql[:tunable][:max_connections] = \"800\" \n* mysql[:tunable][:wait_timeout] = \"180\" \n* mysql[:tunable][:net_write_timeout] = \"30\" \n* mysql[:tunable][:net_write_timeout] = \"30\" \n* mysql[:tunable][:back_log] = \"128\" \n* mysql[:tunable][:table_cache] = \"128\" \n* mysql[:tunable][:max_heap_table_size] = \"32M\" \n\n= USAGE:\n\nOn client nodes,\n\n include_recipe \"mysql::client\"\n \nAs the common use case is on systems with Ruby, we also install the MySQL RubyGem. Because we may want to be able to use the gem within another Chef recipe, we make sure the mysql development package and gem are installed first. The key is this:\n\n r = package ... do\n action :nothing\n end\n \n r.run_action(:install)\n \nThis creates a resource object for the package and does the installation before other recipes are parsed. You'll need to have the C compiler and such (ie, build-essential on Ubuntu) before running the recipes, but we already do that when installing Chef :-). If you want to be able to access a MySQL database via Ruby within another recipe, you could do so, like so:\n\n Gem.clear_paths # needed for Chef to find the gem...\n require 'mysql' # requires the mysql gem\n\n execute \"create #{node[:railsapp][:db][:database]} database\" do\n command \"/usr/bin/mysqladmin -u root -p#{node[:mysql][:server_root_password]} create #{node[:railsapp][:db][:database]}\"\n not_if do\n m = Mysql.new(\"localhost\", \"root\", @node[:mysql][:server_root_password])\n m.list_dbs.include?(@node[:railsapp][:db][:database])\n end\n end\n\nOn server nodes, \n\n include_recipe \"mysql::server\"\n \nOn Debian/Ubuntu this will preseed the MySQL package with the randomly generated root password. You can of course change the password afterward, but this makes sure that there's a good password set. You can view it in the node data in the Chef Server webui. Sets a new password for debian-sys-maint user as well.\n\nAlso sets up 'repl' user grants for replication slaves.\n\nOn EC2 nodes,\n\n include_recipe \"mysql::server_ec2\"\n \nWhen the ec2_path doesn't exist we look for a mounted filesystem (eg, EBS) and move the datadir there.\n\nThe client recipe is already included by server and 'default' recipes.\n\n= LICENSE and AUTHOR:\n \nAuthor:: Joshua Timberman ()\nAuthor:: AJ Christensen ()\n\nCopyright:: 2009, Opscode, Inc\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n", "maintainer" : "Opscode, Inc.", "maintainer_email" : "cookbooks@opscode.com", "name" : "mysql", "platforms" : { "debian" : "", "ubuntu" : "" }, "providing" : { }, "recipes" : { "mysql::client" : "Installs packages required for mysql clients using run_action magic", "mysql::server" : "Installs packages required for mysql servers w/o manual intervention", "mysql::server_ec2" : "Performs EC2-specific mountpoint manipulation" }, "recommendations" : { }, "replacing" : { }, "suggestions" : { }, "version" : "0.21.2" }, "name" : "mysql-0.21.2", "providers" : [ { "checksum" : "b994881a2aba60e32c4b6408ffba993d", "name" : "database.rb", "path" : "providers/database.rb", "specificity" : "default", "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-b994881a2aba60e32c4b6408ffba993d?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=2XMRbryCmEqirCWLCvrXoenYubw%3D" } ], "recipes" : [ { "checksum" : "f51bd8122b7dccc9f4656319fef3252a", "name" : "server_ec2.rb", "path" : "recipes/server_ec2.rb", "specificity" : "default", "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-f51bd8122b7dccc9f4656319fef3252a?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=BUR2mosCvmoOKq4Mkh3JUG0MY38%3D" }, { "checksum" : "80daa897597560372d017c58c4df0e3c", "name" : "server.rb", "path" : "recipes/server.rb", "specificity" : "default", "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-80daa897597560372d017c58c4df0e3c?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=bU3j9Nw%2BnuIroXKrlJZe7tjaugA%3D" }, { "checksum" : "bd3ba2d05dea6a8cf0dc2a45f540cc32", "name" : "default.rb", "path" : "recipes/default.rb", "specificity" : "default", "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-bd3ba2d05dea6a8cf0dc2a45f540cc32?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=7haumT5EtEM2h8l32efqV%2Fik%2BdY%3D" }, { "checksum" : "a1d679c7480267cd9b69e3194c7e45ab", "name" : "client.rb", "path" : "recipes/client.rb", "specificity" : "default", "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-a1d679c7480267cd9b69e3194c7e45ab?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=ZhfTiwv1aXC7HZMnW8A7i4vkMCM%3D" } ], "resources" : [ { "checksum" : "8aa8e2cafe54c2932c7aa65d62ec2695", "name" : "database.rb", "path" : "resources/database.rb", "specificity" : "default", "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-8aa8e2cafe54c2932c7aa65d62ec2695?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=6URS94f1HpRibHC%2FhBkr7Eg3dVA%3D" } ], "root_files" : [ { "checksum" : "e9278fc99fd668bdce33d72dc71fade9", "name" : "README.rdoc", "path" : "README.rdoc", "specificity" : "default", "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-e9278fc99fd668bdce33d72dc71fade9?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=KPgAGqShEO5SGzz8oRdwIInPUOc%3D" }, { "checksum" : "8d2f9635f4817ff905a4124e09ec6c59", "name" : "metadata.rb", "path" : "metadata.rb", "specificity" : "default", "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-8d2f9635f4817ff905a4124e09ec6c59?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=fPF2iY7tNrq%2FuNrCjRLImP9vRbA%3D" }, { "checksum" : "e6804b8f3e6dfdbbece9d319537ffea1", "name" : "metadata.json", "path" : "metadata.json", "specificity" : "default", "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-e6804b8f3e6dfdbbece9d319537ffea1?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=EVsALLreeAA41%2BiPAfPt%2FxFEIYI%3D" } ], "templates" : [ { "checksum" : "689c1b6fbb242b6c508384e56646341d", "name" : "my.cnf.erb", "path" : "templates/ubuntu-9.10/my.cnf.erb", "specificity" : "ubuntu-9.10", "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-689c1b6fbb242b6c508384e56646341d?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=2ugp0XVvvUktYdBxfC9bCZBjOs4%3D" }, { "checksum" : "16b036a0bb31957a77e9b825cf616cc5", "name" : "mysql-server.seed.erb", "path" : "templates/default/mysql-server.seed.erb", "specificity" : "default", "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-16b036a0bb31957a77e9b825cf616cc5?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=50bRvt6GQqFEcfYtaIsq1d4a4c8%3D" }, { "checksum" : "932b51ddddcbd24ee10a76ecae33b8ba", "name" : "grants.sql.erb", "path" : "templates/default/grants.sql.erb", "specificity" : "default", "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-932b51ddddcbd24ee10a76ecae33b8ba?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=RHR0obLFcsN1M9tL28IH4Tcur5g%3D" }, { "checksum" : "7746560b37ac8d4a0cf68befbecbd8a3", "name" : "my.cnf.erb", "path" : "templates/default/my.cnf.erb", "specificity" : "default", "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-7746560b37ac8d4a0cf68befbecbd8a3?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=W7Nqkvhw2TBrlDvcM2rlA4Oj5%2Bk%3D" }, { "checksum" : "63bd67fae6d297e8f658e9c0ad01a411", "name" : "my.cnf.erb", "path" : "templates/centos/my.cnf.erb", "specificity" : "centos", "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-63bd67fae6d297e8f658e9c0ad01a411?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=oFcRya56f%2F4oJBGrIvk4XcWQFm4%3D" }, { "checksum" : "689c1b6fbb242b6c508384e56646341d", "name" : "my.cnf.erb", "path" : "templates/ubuntu-10.04/my.cnf.erb", "specificity" : "ubuntu-10.04", "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-689c1b6fbb242b6c508384e56646341d?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=2ugp0XVvvUktYdBxfC9bCZBjOs4%3D" }, { "checksum" : "63bd67fae6d297e8f658e9c0ad01a411", "name" : "my.cnf.erb", "path" : "templates/redhat/my.cnf.erb", "specificity" : "redhat", "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-63bd67fae6d297e8f658e9c0ad01a411?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=oFcRya56f%2F4oJBGrIvk4XcWQFm4%3D" }, { "checksum" : "d2244150a145b3f658cd37c13269fafc", "name" : "port_mysql.erb", "path" : "templates/default/port_mysql.erb", "specificity" : "default", "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-d2244150a145b3f658cd37c13269fafc?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=23iHcjwpNOvlNf%2BlrKcV2pkU7uo%3D" }, { "checksum" : "2e08553db526f5f80c28b343f6a616cb", "name" : "debian.cnf.erb", "path" : "templates/default/debian.cnf.erb", "specificity" : "default", "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-2e08553db526f5f80c28b343f6a616cb?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=VdcFYxnLUkj1tS3k8DovrzZEA7E%3D" }, { "checksum" : "1e5068eec65b51f5a327580fb0af4677", "name" : "my.cnf.erb", "path" : "templates/ubuntu-8.04/my.cnf.erb", "specificity" : "ubuntu-8.04", "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-1e5068eec65b51f5a327580fb0af4677?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277774082&Signature=D5lPeu1UQvA9pEXZm5nVOwj3WIo%3D" } ], "version" : "0.21.2" } ================================================ FILE: apis/chef/src/test/resources/node.json ================================================ { "automatic" : { }, "chef_environment" : "prod", "chef_type" : "node", "default" : { }, "json_class" : "Chef::Node", "name" : "adrian-jcloudstest", "normal" : { "tomcat6" : { "ssl_port" : 8433 } }, "override" : { }, "run_list" : [ "recipe[java]" ] } ================================================ FILE: apis/chef/src/test/resources/nodes_list.json ================================================ { "blah": "https://api.opscode.com/org/directory/nodes/blah", "boxer": "https://api.opscode.com/org/directory/nodes/boxer", "blarrrrgh": "https://api.opscode.com/org/directory/nodes/blarrrrgh" } ================================================ FILE: apis/chef/src/test/resources/privkey.txt ================================================ -----BEGIN RSA PRIVATE KEY----- MIIEpAIBAAKCAQEA0ueqo76MXuP6XqZBILFziH/9AI7C6PaN5W0dSvkr9yInyGHS z/IR1+4tqvP2qlfKVKI4CP6BFH251Ft9qMUBuAsnlAVQ1z0exDtIFFOyQCdR7iXm jBIWMSS4buBwRQXwDK7id1OxtU23qVJv+xwEV0IzaaSJmaGLIbvRBD+qatfUuQJB MU/04DdJIwvLtZBYdC2219m5dUBQaa4bimL+YN9EcsDzD9h9UxQo5ReK7b3cNMzJ BKJWLzFBcJuePMzAnLFktr/RufX4wpXe6XJxoVPaHo72GorLkwnQ0HYMTY8rehT4 mDi1FI969LHCFFaFHSAaRnwdXaQkJmSfcxzCYQIDAQABAoIBAQCW3I4sKN5B9jOe xq/pkeWBq4OvhW8Ys1yW0zFT8t6nHbB1XrwscQygd8gE9BPqj3e0iIEqtdphbPmj VHqTYbC0FI6QDClifV7noTwTBjeIOlgZ0NSUN0/WgVzIOxUz2mZ2vBZUovKILPqG TOi7J7RXMoySMdcXpP1f+PgvYNcnKsT72UcWaSXEV8/zo+Zm/qdGPVWwJonri5Mp DVm5EQSENBiRyt028rU6ElXORNmoQpVjDVqZ1gipzXkifdjGyENw2rt4V/iKYD7V 5iqXOsvP6Cemf4gbrjunAgDG08S00kiUgvVWcdXW+dlsR2nCvH4DOEe3AYYh/aH8 DxEE7FbtAoGBAPcNO8fJ56mNw0ow4Qg38C+Zss/afhBOCfX4O/SZKv/roRn5+gRM KRJYSVXNnsjPI1plzqR4OCyOrjAhtuvL4a0DinDzf1+fiztyNohwYsW1vYmqn3ti EN0GhSgE7ppZjqvLQ3f3LUTxynhA0U+k9wflb4irIlViTUlCsOPkrNJDAoGBANqL Q+vvuGSsmRLU/Cenjy+Mjj6+QENg51dz34o8JKuVKIPKU8pNnyeLa5fat0qD2MHm OB9opeQOcw0dStodxr6DB3wi83bpjeU6BWUGITNiWEaZEBrQ0aiqNJJKrrHm8fAZ 9o4l4oHc4hI0kYVYYDuxtKuVJrzZiEapTwoOcYiLAoGBAI/EWbeIHZIj9zOjgjEA LHvm25HtulLOtyk2jd1njQhlHNk7CW2azIPqcLLH99EwCYi/miNH+pijZ2aHGCXb /bZrSxM0ADmrZKDxdB6uGCyp+GS2sBxjEyEsfCyvwhJ8b3Q100tqwiNO+d5FCglp HICx2dgUjuRVUliBwOK93nx1AoGAUI8RhIEjOYkeDAESyhNMBr0LGjnLOosX+/as qiotYkpjWuFULbibOFp+WMW41vDvD9qrSXir3fstkeIAW5KqVkO6mJnRoT3Knnra zjiKOITCAZQeiaP8BO5o3pxE9TMqb9VCO3ffnPstIoTaN4syPg7tiGo8k1SklVeH 2S8lzq0CgYAKG2fljIYWQvGH628rp4ZcXS4hWmYohOxsnl1YrszbJ+hzR+IQOhGl YlkUQYXhy9JixmUUKtH+NXkKX7Lyc8XYw5ETr7JBT3ifs+G7HruDjVG78EJVojbd 8uLA+DdQm5mg4vd1GTiSK65q/3EeoBlUaVor3HhLFki+i9qpT8CBsg== -----END RSA PRIVATE KEY----- ================================================ FILE: apis/chef/src/test/resources/pubkey.txt ================================================ -----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ueqo76MXuP6XqZBILFz iH/9AI7C6PaN5W0dSvkr9yInyGHSz/IR1+4tqvP2qlfKVKI4CP6BFH251Ft9qMUB uAsnlAVQ1z0exDtIFFOyQCdR7iXmjBIWMSS4buBwRQXwDK7id1OxtU23qVJv+xwE V0IzaaSJmaGLIbvRBD+qatfUuQJBMU/04DdJIwvLtZBYdC2219m5dUBQaa4bimL+ YN9EcsDzD9h9UxQo5ReK7b3cNMzJBKJWLzFBcJuePMzAnLFktr/RufX4wpXe6XJx oVPaHo72GorLkwnQ0HYMTY8rehT4mDi1FI969LHCFFaFHSAaRnwdXaQkJmSfcxzC YQIDAQAB -----END PUBLIC KEY----- ================================================ FILE: apis/chef/src/test/resources/roles_list.json ================================================ { "webserver": "http://localhost:4000/roles/webserver", "smtpserver": "http://localhost:4000/roles/smtpserver" } ================================================ FILE: apis/chef/src/test/resources/sandbox.json ================================================ { "_rev": "1-8c27b0ea4c2b7aaedbb44cfbdfcc11b2", "json_class": "Chef::Sandbox", "is_completed": false, "create_time": "2010-07-07T03:36:00+00:00", "chef_type": "sandbox", "checksums": [], "name": "f9d6d9b72bae465890aae87969f98a9c", "guid": "f9d6d9b72bae465890aae87969f98a9c" } ================================================ FILE: apis/chef/src/test/resources/search_role.json ================================================ { "total": 1, "start": 0, "rows": [ { "name": "webserver", "description": "The base role for systems that serve HTTP traffic", "json_class": "Chef::Role", "default_attributes": { "apache2": { "listen_ports": [ "80", "443" ] } }, "override_attributes": { "apache2": { "max_children": "50" } }, "chef_type": "role", "run_list": [], "env_run_lists": { "prod": [ "recipe[apache2]" ], "staging": [ "recipe[apache2::staging]" ] } } ] } ================================================ FILE: apis/chef/src/test/resources/search_role_empty.json ================================================ { "total": 0, "start": 0, "rows": [] } ================================================ FILE: apis/chef/src/test/resources/tomcat-cookbook.json ================================================ { "attributes" : [ { "checksum" : "6e3fd0d16a87a55c569da108194ecb29", "name" : "tomcat6.rb", "path" : "attributes/tomcat6.rb", "specificity" : "default", "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-6e3fd0d16a87a55c569da108194ecb29?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=zvYjsgUXIC7Xj3MT8Wd93esDGJM%3D" } ], "chef_type" : "cookbook_version", "cookbook_name" : "tomcat6", "definitions" : [ ], "files" : [ { "checksum" : "18e534a72652f3d53b197ca4e5027009", "name" : "org.apache.tomcat.tomcat6.plist", "path" : "files/default/org.apache.tomcat.tomcat6.plist", "specificity" : "default", "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-18e534a72652f3d53b197ca4e5027009?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=M3fBL4t7uuYVXVah2PyZ8eL1QCc%3D" }, { "checksum" : "6a35ce92050296862ea63b784529d2e0", "name" : "logging.properties", "path" : "files/default/logging.properties", "specificity" : "default", "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-6a35ce92050296862ea63b784529d2e0?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=vRlKoye2%2Fwz8mdQI%2F3Ht916sllE%3D" } ], "json_class" : "Chef::CookbookVersion", "libraries" : [ { "checksum" : "2b6f7847142bb36823c570899669c54b", "name" : "tomcat_manager.rb", "path" : "libraries/tomcat_manager.rb", "specificity" : "default", "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-2b6f7847142bb36823c570899669c54b?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=zxIoUKcGYWo9ir6qf1tTy3wvKZ4%3D" }, { "checksum" : "24db7b7dd6f04f8da5fa2b282910ac08", "name" : "tomcat.rb", "path" : "libraries/tomcat.rb", "specificity" : "default", "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-24db7b7dd6f04f8da5fa2b282910ac08?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=c4Gbn5kX0ZaPbWvk5LAcR77sITg%3D" } ], "metadata" : { "attributes" : { "tomcat6/with_native" : { "calculated" : false, "choice" : [ ], "default" : "false", "description" : "works for centos, install tomcat-native libraries", "display_name" : "Tomcat native support", "recipes" : [ ], "required" : "optional", "type" : "string" } }, "conflicting" : { }, "dependencies" : { }, "description" : "Installs and configures all aspects of tomcat6 using custom local installation", "groupings" : { }, "license" : "Apache 2.0", "long_description" : "= DESCRIPTION:\n\nInstalls Tomcat6\n\n= REQUIREMENTS:\n\n== Platform and Application Environment:\n\nTested on Centos 5.2 8.10. May work on other platforms, esp Redhat.\nNeeds Java at least Java 5\n\n== Cookbooks:\n\nOpscode cookbooks, http://github.com/opscode/cookbooks/tree/master:\n\n* java\n\n= ATTRIBUTES: \n\n= USAGE:\n\n\n= LICENSE and AUTHOR:\n \nAuthor:: Edmund Haselwanter ()\nCopyright:: 2009, Edmund Haselwanter\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n", "maintainer" : "Opscode, Inc.", "maintainer_email" : "cookbooks@opscode.com", "name" : "tomcat6", "platforms" : { "centos" : "", "debian" : "", "redhat" : "", "ubuntu" : "" }, "providing" : { }, "recipes" : { "tomcat6" : "Main Tomcat 6 configuration" }, "recommendations" : { }, "replacing" : { }, "suggestions" : { }, "version" : "0.1.0" }, "name" : "tomcat6-0.1.0", "providers" : [ ], "recipes" : [ { "checksum" : "d45661e4b50f9677de7b8684af26ff9d", "name" : "default.rb", "path" : "recipes/default.rb", "specificity" : "default", "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-d45661e4b50f9677de7b8684af26ff9d?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=r3CvyVe7dcOzB%2F0fNAun5ldGwr8%3D" } ], "resources" : [ ], "root_files" : [ { "checksum" : "14f6977f68c3674484e8289e361fb5a4", "name" : "README.rdoc", "path" : "README.rdoc", "specificity" : "default", "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-14f6977f68c3674484e8289e361fb5a4?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=VNZxN%2B7CxO7ZbDHJOS%2FaTtpkPaE%3D" }, { "checksum" : "abc416ffba9ea64ca71635191cb87af6", "name" : "metadata.rb", "path" : "metadata.rb", "specificity" : "default", "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-abc416ffba9ea64ca71635191cb87af6?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=pemynt9Q1F%2BxlS26kLaz%2F4NDGO4%3D" }, { "checksum" : "dd8473a8a7f2b446250ecdefb1882a5e", "name" : "metadata.json", "path" : "metadata.json", "specificity" : "default", "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-dd8473a8a7f2b446250ecdefb1882a5e?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=sHpayqP%2Fe4Luv20EMa3q%2FaMN4ms%3D" } ], "templates" : [ { "checksum" : "107263b81e4700cf0adad7af2a133bbd", "name" : "tomcat-users.xml.erb", "path" : "templates/default/tomcat-users.xml.erb", "specificity" : "default", "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-107263b81e4700cf0adad7af2a133bbd?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=QC7MNIauR2ox5MVlohf2i73uM1s%3D" }, { "checksum" : "fa4432b353fa57b9da26a4bff44285f2", "name" : "sv-tomcat6-run.erb", "path" : "templates/default/sv-tomcat6-run.erb", "specificity" : "default", "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-fa4432b353fa57b9da26a4bff44285f2?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=q2rDeJFeh4oyhfv9ExMifGB0wxo%3D" }, { "checksum" : "33fd6f63133e7ebe28bc62e58773c408", "name" : "manager.xml.erb", "path" : "templates/default/manager.xml.erb", "specificity" : "default", "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-33fd6f63133e7ebe28bc62e58773c408?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=rIijEhwLPf5PWTJOg%2BElbOquPBM%3D" }, { "checksum" : "09f2bf988663175cd1b7973198dfb5eb", "name" : "sv-tomcat6-log-run.erb", "path" : "templates/default/sv-tomcat6-log-run.erb", "specificity" : "default", "url" : "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/checksum-09f2bf988663175cd1b7973198dfb5eb?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277771874&Signature=UnfNDP4pDzPM3PoLcLWyTnTa%2FKI%3D" } ], "version" : "0.1.0" } ================================================ FILE: apis/chef/src/test/resources/upload-site.json ================================================ { "uri": "https://api.opscode.com/organizations/jclouds/sandboxes/d454f71e2a5f400c808d0c5d04c2c88c", "checksums": { "0c5ecd7788cf4f6c7de2a57193897a6c": { "url": "https://s3.amazonaws.com/opscode-platform-production-data/organization-486ca3ac66264fea926aa0b4ff74341c/sandbox-d454f71e2a5f400c808d0c5d04c2c88c/checksum-0c5ecd7788cf4f6c7de2a57193897a6c?AWSAccessKeyId=AKIAJOZTD2N26S7W6APA&Expires=1277344702&Signature=FtKyqvYEjhhEKmRY%2B0M8aGPMM7g%3D", "needs_upload": true }, "0189e76ccc476701d6b374e5a1a27347": { "needs_upload": false }, "1dda05ed139664f1f89b9dec482b77c0": { "needs_upload": false } }, "sandbox_id": "d454f71e2a5f400c808d0c5d04c2c88c" } ================================================ FILE: apis/chef/src/test/resources/user.json ================================================ { "display_name" : "Ignasi Barrera", "email" : "myemail@chef.org", "first_name" : "Ignasi", "last_name" : "Barrera", "middle_name" : "", "public_key" : "-----BEGIN RSA PUBLIC KEY-----\nMIIBCgKCAQEAp0ytgXbPzqJwOOixn7bTa6VAiNvVIOn+yDPoWbyEfc0li93BHIwv\n01KW/mn55IXnSbMw86rdxisvwPHFfb7URuKuTzME6yrphBiancmNjushZZeBWb8j\nqJhnFIKbaaOqew0LZSyG9ycYODB/HDK/pWTV4Bd1OtLHBNFrnIf+r3HOjJsa4rmK\nWXgSQIQO7be/iRHysApV9tfVH8lo1ETnA08JTrQwDgo9St9YNbydb5V0CiLiQsOa\nIbY09buUK9lXthh/rrRVbGbSwQM6OYdXIEZTN2BFvQ0p5pH8AiTwFqb0ICO46a0S\njfGcXNjC/QfHljAPY3T5xyIOODM8afHCnwIDAQAB\n-----END RSA PUBLIC KEY-----\n", "username" : "nacx" } ================================================ FILE: apis/cloudstack/bnd.bnd ================================================ Export-Package: \ org.jclouds.cloudstack.*;version="${project.version}";-noimport:=true ================================================ FILE: apis/cloudstack/pom.xml ================================================ 4.0.0 org.apache.jclouds jclouds-project 2.7.1-SNAPSHOT ../../project/pom.xml org.apache.jclouds.api cloudstack jclouds cloudstack core jclouds components to access cloudstack http://localhost:8080/client/api 3.0.3 FIXME_apiKey FIXME_secretKey osFamily=CENTOS org.apache.jclouds jclouds-core ${project.version} org.apache.jclouds jclouds-core ${project.version} test-jar test org.apache.jclouds jclouds-compute ${project.version} org.apache.jclouds jclouds-compute ${project.version} test-jar test org.apache.jclouds.driver jclouds-sshj ${project.version} test org.apache.jclouds.driver jclouds-slf4j ${project.version} test ch.qos.logback logback-classic test com.google.auto.service auto-service true live org.apache.maven.plugins maven-surefire-plugin integration integration-test test 2 ${test.cloudstack.endpoint} ${test.cloudstack.api-version} ${test.cloudstack.build-version} ${test.cloudstack.identity} ${test.cloudstack.credential} ${test.cloudstack.template} ${test.cloudstack.domainAdminIdentity} ${test.cloudstack.domainAdminCredential} ${test.cloudstack.globalAdminIdentity} ${test.cloudstack.globalAdminCredential} ================================================ FILE: apis/cloudstack/src/main/java/org/jclouds/cloudstack/AsyncJobException.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.cloudstack; public class AsyncJobException extends RuntimeException { public AsyncJobException() { } public AsyncJobException(String s) { super(s); } public AsyncJobException(String s, Throwable throwable) { super(s, throwable); } public AsyncJobException(Throwable throwable) { super(throwable); } } ================================================ FILE: apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackApi.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.cloudstack; import java.io.Closeable; import org.jclouds.cloudstack.features.AccountApi; import org.jclouds.cloudstack.features.AddressApi; import org.jclouds.cloudstack.features.AsyncJobApi; import org.jclouds.cloudstack.features.ConfigurationApi; import org.jclouds.cloudstack.features.EventApi; import org.jclouds.cloudstack.features.FirewallApi; import org.jclouds.cloudstack.features.GuestOSApi; import org.jclouds.cloudstack.features.HypervisorApi; import org.jclouds.cloudstack.features.ISOApi; import org.jclouds.cloudstack.features.LimitApi; import org.jclouds.cloudstack.features.LoadBalancerApi; import org.jclouds.cloudstack.features.NATApi; import org.jclouds.cloudstack.features.NetworkApi; import org.jclouds.cloudstack.features.OfferingApi; import org.jclouds.cloudstack.features.ProjectApi; import org.jclouds.cloudstack.features.SSHKeyPairApi; import org.jclouds.cloudstack.features.SecurityGroupApi; import org.jclouds.cloudstack.features.SessionApi; import org.jclouds.cloudstack.features.SnapshotApi; import org.jclouds.cloudstack.features.TagApi; import org.jclouds.cloudstack.features.TemplateApi; import org.jclouds.cloudstack.features.VMGroupApi; import org.jclouds.cloudstack.features.VirtualMachineApi; import org.jclouds.cloudstack.features.VolumeApi; import org.jclouds.cloudstack.features.ZoneApi; import org.jclouds.rest.annotations.Delegate; /** * Provides synchronous access to CloudStack. *

* * @see */ public interface CloudStackApi extends Closeable { /** * Provides synchronous access to Zone features. */ @Delegate ZoneApi getZoneApi(); /** * Provides synchronous access to Template features. */ @Delegate TemplateApi getTemplateApi(); /** * Provides synchronous access to Service, Disk, and Network Offering * features. */ @Delegate OfferingApi getOfferingApi(); /** * Provides synchronous access to Network features. */ @Delegate NetworkApi getNetworkApi(); /** * Provides synchronous access to VirtualMachine features. */ @Delegate VirtualMachineApi getVirtualMachineApi(); /** * Provides synchronous access to SecurityGroup features. */ @Delegate SecurityGroupApi getSecurityGroupApi(); /** * Provides synchronous access to AsyncJob features. */ @Delegate AsyncJobApi getAsyncJobApi(); /** * Provides synchronous access to Address features. */ @Delegate AddressApi getAddressApi(); /** * Provides synchronous access to NAT features. */ @Delegate NATApi getNATApi(); /** * Provides synchronous access to Firewall features. */ @Delegate FirewallApi getFirewallApi(); /** * Provides synchronous access to LoadBalancer features. */ @Delegate LoadBalancerApi getLoadBalancerApi(); /** * Provides synchronous access to GuestOS features. */ @Delegate GuestOSApi getGuestOSApi(); /** * Provides synchronous access to Hypervisor features. */ @Delegate HypervisorApi getHypervisorApi(); /** * Provides synchronous access to Configuration features. */ @Delegate ConfigurationApi getConfigurationApi(); /** * Provides synchronous access to Account features. */ @Delegate AccountApi getAccountApi(); /** * Provides synchronous access to SSH Keypairs */ @Delegate SSHKeyPairApi getSSHKeyPairApi(); /** * Provides synchronous access to VM groups */ @Delegate VMGroupApi getVMGroupApi(); /** * Provides synchronous access to Events */ @Delegate EventApi getEventApi(); /** * Provides synchronous access to Resource Limits */ @Delegate LimitApi getLimitApi(); /** * Provides synchronous access to ISOs */ @Delegate ISOApi getISOApi(); /** * Provides synchronous access to Volumes */ @Delegate VolumeApi getVolumeApi(); /** * Provides synchronous access to Snapshots */ @Delegate SnapshotApi getSnapshotApi(); /** * Provides synchronous access to Sessions */ @Delegate SessionApi getSessionApi(); /** * Provides synchronous access to Projects */ @Delegate ProjectApi getProjectApi(); /** * Provides synchronous access to Tags */ @Delegate TagApi getTagApi(); } ================================================ FILE: apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackApiMetadata.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.cloudstack; import static org.jclouds.cloudstack.config.CloudStackProperties.AUTO_GENERATE_KEYPAIRS; import static org.jclouds.reflect.Reflection2.typeToken; import java.net.URI; import java.util.Properties; import org.jclouds.apis.ApiMetadata; import org.jclouds.cloudstack.compute.config.CloudStackComputeServiceContextModule; import org.jclouds.cloudstack.config.CloudStackHttpApiModule; import org.jclouds.cloudstack.config.CloudStackParserModule; import org.jclouds.rest.internal.BaseHttpApiMetadata; import com.google.auto.service.AutoService; import com.google.common.collect.ImmutableSet; import com.google.inject.Module; /** * Implementation of {@link ApiMetadata} for Citrix/Apache CloudStack api. */ @AutoService(ApiMetadata.class) public class CloudStackApiMetadata extends BaseHttpApiMetadata { @Override public Builder toBuilder() { return new Builder().fromApiMetadata(this); } public CloudStackApiMetadata() { this(new Builder()); } protected CloudStackApiMetadata(Builder builder) { super(builder); } public static Properties defaultProperties() { Properties properties = BaseHttpApiMetadata.defaultProperties(); properties.setProperty("jclouds.ssh.max-retries", "7"); properties.setProperty("jclouds.ssh.retry-auth", "true"); properties.setProperty(AUTO_GENERATE_KEYPAIRS, "false"); return properties; } public static class Builder extends BaseHttpApiMetadata.Builder { @SuppressWarnings("deprecation") protected Builder() { id("cloudstack") .name("Citrix CloudStack API") .identityName("API Key") .credentialName("Secret Key") .documentation(URI.create("http://download.cloud.com/releases/2.2.0/api_2.2.12/TOC_User.html")) .defaultEndpoint("http://localhost:8080/client/api") .version("2.2") .view(typeToken(CloudStackContext.class)) .defaultProperties(CloudStackApiMetadata.defaultProperties()) .defaultModules(ImmutableSet.> builder() .add(CloudStackParserModule.class) .add(CloudStackHttpApiModule.class) .add(CloudStackComputeServiceContextModule.class).build()); } @Override public CloudStackApiMetadata build() { return new CloudStackApiMetadata(this); } @Override protected Builder self() { return this; } } } ================================================ FILE: apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackContext.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.cloudstack; import org.jclouds.cloudstack.internal.CloudStackContextImpl; import org.jclouds.compute.ComputeServiceContext; import com.google.inject.ImplementedBy; @ImplementedBy(CloudStackContextImpl.class) public interface CloudStackContext extends ComputeServiceContext { CloudStackApi getApi(); CloudStackDomainApi getDomainApi(); CloudStackGlobalApi getGlobalApi(); } ================================================ FILE: apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackDomainApi.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.cloudstack; import org.jclouds.cloudstack.features.DomainAccountApi; import org.jclouds.cloudstack.features.DomainDomainApi; import org.jclouds.cloudstack.features.DomainLimitApi; import org.jclouds.cloudstack.features.DomainUserApi; import org.jclouds.rest.annotations.Delegate; /** * Provides synchronous access to CloudStack. *

* * @see */ public interface CloudStackDomainApi extends CloudStackApi { /** * Provides synchronous access to Resource Limits */ @Delegate @Override DomainLimitApi getLimitApi(); /** * Provides synchronous access to Accounts */ @Delegate @Override DomainAccountApi getAccountApi(); /** * Provides synchronous access to Users */ @Delegate DomainUserApi getUserClient(); /** * Provides synchronous access to Domains */ @Delegate DomainDomainApi getDomainClient(); } ================================================ FILE: apis/cloudstack/src/main/java/org/jclouds/cloudstack/CloudStackGlobalApi.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.cloudstack; import org.jclouds.cloudstack.features.GlobalAccountApi; import org.jclouds.cloudstack.features.GlobalAlertApi; import org.jclouds.cloudstack.features.GlobalCapacityApi; import org.jclouds.cloudstack.features.GlobalConfigurationApi; import org.jclouds.cloudstack.features.GlobalDomainApi; import org.jclouds.cloudstack.features.GlobalHostApi; import org.jclouds.cloudstack.features.GlobalOfferingApi; import org.jclouds.cloudstack.features.GlobalPodApi; import org.jclouds.cloudstack.features.GlobalStoragePoolApi; import org.jclouds.cloudstack.features.GlobalUsageApi; import org.jclouds.cloudstack.features.GlobalUserApi; import org.jclouds.cloudstack.features.GlobalVlanApi; import org.jclouds.cloudstack.features.GlobalZoneApi; import org.jclouds.rest.annotations.Delegate; /** * Provides synchronous access to CloudStack. *

* * @see */ public interface CloudStackGlobalApi extends CloudStackDomainApi { /** * Provides synchronous access to Accounts */ @Delegate @Override GlobalAccountApi getAccountApi(); /** * Provides synchronous access to Users */ @Delegate @Override GlobalUserApi getUserClient(); /** * Provides synchronous access to Alerts */ @Delegate GlobalAlertApi getAlertClient(); /** * Provides synchronous access to Capacities */ @Delegate GlobalCapacityApi getCapacityClient(); /** * Provides synchronous access to Offerings */ @Delegate @Override GlobalOfferingApi getOfferingApi(); /** * Provides synchronous access to Hosts */ @Delegate GlobalHostApi getHostClient(); /** * Provides synchronous access to Storage Pools */ @Delegate GlobalStoragePoolApi getStoragePoolClient(); /** * Provides synchronous access to Usage */ @Delegate GlobalUsageApi getUsageClient(); /** * Provides synchronous access to Configuration */ @Delegate @Override GlobalConfigurationApi getConfigurationApi(); /** * Provides synchronous access to Domain */ @Delegate @Override GlobalDomainApi getDomainClient(); /** * Provides synchronous access to Zone */ @Delegate @Override GlobalZoneApi getZoneApi(); /** * Provides synchronous access to Pod */ @Delegate GlobalPodApi getPodClient(); /** * Provides synchronous access to Vlan */ @Delegate GlobalVlanApi getVlanClient(); } ================================================ FILE: apis/cloudstack/src/main/java/org/jclouds/cloudstack/binders/BindAccountSecurityGroupPairsToIndexedQueryParams.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.cloudstack.binders; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static org.jclouds.http.Uris.uriBuilder; import static org.jclouds.http.utils.Queries.queryParser; import java.net.URI; import java.util.Map.Entry; import jakarta.inject.Singleton; import org.jclouds.http.HttpRequest; import org.jclouds.rest.Binder; import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableMultimap.Builder; import com.google.common.collect.Multimap; @Singleton public class BindAccountSecurityGroupPairsToIndexedQueryParams implements Binder { @SuppressWarnings("unchecked") @Override public R bindToRequest(R request, Object input) { checkArgument(input instanceof Multimap, "this binder is only valid for Multimaps!"); Multimap pairs = (Multimap) checkNotNull(input, "account group pairs"); checkArgument(!pairs.isEmpty(), "you must specify at least one account, group pair"); Multimap existingParams = queryParser().apply(request.getEndpoint().getQuery()); Builder map = ImmutableMultimap. builder().putAll(existingParams); int i = 0; for (Entry entry : pairs.entries()) map.put(String.format("usersecuritygrouplist[%d].account", i), entry.getKey()).put( String.format("usersecuritygrouplist[%d].group", i++), entry.getValue()); URI endpoint = uriBuilder(request.getEndpoint()).query(map.build()).build(); return (R) request.toBuilder().endpoint(endpoint).build(); } } ================================================ FILE: apis/cloudstack/src/main/java/org/jclouds/cloudstack/binders/BindCIDRsToCommaDelimitedQueryParam.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.cloudstack.binders; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import jakarta.inject.Singleton; import org.jclouds.http.HttpRequest; import org.jclouds.rest.Binder; import com.google.common.base.Joiner; import com.google.common.collect.Iterables; @Singleton public class BindCIDRsToCommaDelimitedQueryParam implements Binder { @SuppressWarnings("unchecked") @Override public R bindToRequest(R request, Object input) { checkArgument(input instanceof Iterable, "this binder is only valid for Iterables!"); Iterable cidrs = (Iterable) checkNotNull(input, "cidr list"); checkArgument(!Iterables.isEmpty(cidrs), "you must specify at least one cidr range"); return (R) request.toBuilder().replaceQueryParam("cidrlist", Joiner.on(',').join(cidrs)).build(); } } ================================================ FILE: apis/cloudstack/src/main/java/org/jclouds/cloudstack/binders/BindIdListToCommaDelimitedQueryParam.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.cloudstack.binders; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import jakarta.inject.Singleton; import org.jclouds.http.HttpRequest; import org.jclouds.rest.Binder; import com.google.common.base.Joiner; import com.google.common.collect.Iterables; @Singleton public class BindIdListToCommaDelimitedQueryParam implements Binder { @SuppressWarnings("unchecked") @Override public R bindToRequest(R request, Object input) { checkArgument(input instanceof Iterable, "this binder is only valid for Iterables!"); Iterable numbers = (Iterable) checkNotNull(input, "list of Longs"); checkArgument(!Iterables.isEmpty(numbers), "you must specify at least one element"); return (R) request.toBuilder().replaceQueryParam("ids", Joiner.on(',').join(numbers)).build(); } } ================================================ FILE: apis/cloudstack/src/main/java/org/jclouds/cloudstack/binders/BindSnapshotPolicyScheduleToQueryParam.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.cloudstack.binders; import static com.google.common.base.Preconditions.checkArgument; import jakarta.inject.Singleton; import org.jclouds.cloudstack.domain.SnapshotPolicySchedule; import org.jclouds.http.HttpRequest; import org.jclouds.rest.Binder; import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableMultimap.Builder; @Singleton public class BindSnapshotPolicyScheduleToQueryParam implements Binder { @SuppressWarnings("unchecked") @Override public R bindToRequest(R request, Object input) { checkArgument(input instanceof SnapshotPolicySchedule, "this binder is only valid for SnapshotPolicySchedule"); SnapshotPolicySchedule schedule = SnapshotPolicySchedule.class.cast(input); Builder builder = ImmutableMultimap. builder(); builder.put("intervaltype", schedule.getInterval().toString()); builder.put("schedule", schedule.getTime().toString()); return (R) request.toBuilder().replaceQueryParams(builder.build()).build(); } } ================================================ FILE: apis/cloudstack/src/main/java/org/jclouds/cloudstack/binders/BindTemplateMetadataToQueryParams.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.cloudstack.binders; import static com.google.common.base.Preconditions.checkArgument; import org.jclouds.cloudstack.domain.TemplateMetadata; import org.jclouds.http.HttpRequest; import org.jclouds.rest.Binder; import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableMultimap.Builder; public class BindTemplateMetadataToQueryParams implements Binder { @SuppressWarnings("unchecked") @Override public R bindToRequest(R request, Object input) { checkArgument(input instanceof TemplateMetadata, "this binder is only valid for TemplateMetadata"); TemplateMetadata metadata = (TemplateMetadata) input; Builder builder = ImmutableMultimap.builder(); builder.put("name", metadata.getName()); builder.put("ostypeid", metadata.getOsTypeId()); builder.put("displaytext", metadata.getDisplayText()); if (metadata.getSnapshotId() != null) { builder.put("snapshotid", metadata.getSnapshotId()); } if (metadata.getVolumeId() != null) { builder.put("volumeid", metadata.getVolumeId()); } if (metadata.getVirtualMachineId() != null) { builder.put("virtualmachineid", metadata.getVirtualMachineId()); } if (metadata.isPasswordEnabled() != null) { builder.put("passwordenabled", metadata.isPasswordEnabled().toString()); } return (R) request.toBuilder().replaceQueryParams(builder.build()).build(); } } ================================================ FILE: apis/cloudstack/src/main/java/org/jclouds/cloudstack/binders/ResourceLimitToQueryParams.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.cloudstack.binders; import static com.google.common.base.Preconditions.checkArgument; import org.jclouds.cloudstack.domain.ResourceLimit; import org.jclouds.http.HttpRequest; import org.jclouds.rest.Binder; import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableMultimap.Builder; /** * * @see */ public class ResourceLimitToQueryParams implements Binder { @SuppressWarnings("unchecked") @Override public R bindToRequest(R request, Object input) { checkArgument(input instanceof ResourceLimit, "this binder is only valid for ResourceLimit"); ResourceLimit limit = (ResourceLimit) input; Builder builder = ImmutableMultimap. builder(); builder.put("resourcetype", limit.getResourceType().getCode() + ""); builder.put("account", limit.getAccount()); builder.put("domainid", limit.getDomainId()); builder.put("max", limit.getMax() + ""); return (R) request.toBuilder().replaceQueryParams(builder.build()).build(); } } ================================================ FILE: apis/cloudstack/src/main/java/org/jclouds/cloudstack/compute/CloudStackComputeService.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.cloudstack.compute; import static com.google.common.base.Preconditions.checkNotNull; import static org.jclouds.cloudstack.predicates.SshKeyPairPredicates.nameMatches; import static org.jclouds.cloudstack.predicates.ZonePredicates.supportsSecurityGroups; import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING; import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED; import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED; import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import jakarta.inject.Inject; import jakarta.inject.Named; import jakarta.inject.Provider; import jakarta.inject.Singleton; import org.jclouds.Constants; import org.jclouds.cloudstack.CloudStackApi; import org.jclouds.cloudstack.compute.options.CloudStackTemplateOptions; import org.jclouds.cloudstack.domain.SecurityGroup; import org.jclouds.cloudstack.domain.SshKeyPair; import org.jclouds.cloudstack.domain.Zone; import org.jclouds.cloudstack.domain.ZoneAndName; import org.jclouds.cloudstack.predicates.SecurityGroupPredicates; import org.jclouds.collect.Memoized; import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.callables.RunScriptOnNode; import org.jclouds.compute.domain.Hardware; import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.TemplateBuilder; import org.jclouds.compute.extensions.ImageExtension; import org.jclouds.compute.extensions.SecurityGroupExtension; import org.jclouds.compute.extensions.internal.DelegatingImageExtension; import org.jclouds.compute.functions.GroupNamingConvention; import org.jclouds.compute.internal.BaseComputeService; import org.jclouds.compute.internal.PersistNodeCredentials; import org.jclouds.compute.options.TemplateOptions; import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet; import org.jclouds.compute.strategy.DestroyNodeStrategy; import org.jclouds.compute.strategy.GetImageStrategy; import org.jclouds.compute.strategy.GetNodeMetadataStrategy; import org.jclouds.compute.strategy.InitializeRunScriptOnNodeOrPlaceInBadMap; import org.jclouds.compute.strategy.ListNodesStrategy; import org.jclouds.compute.strategy.RebootNodeStrategy; import org.jclouds.compute.strategy.ResumeNodeStrategy; import org.jclouds.compute.strategy.SuspendNodeStrategy; import org.jclouds.domain.Credentials; import org.jclouds.domain.Location; import org.jclouds.scriptbuilder.functions.InitAdminAccess; import com.google.common.base.Function; import com.google.common.base.Optional; import com.google.common.base.Predicate; import com.google.common.base.Supplier; import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.common.collect.Multimap; import com.google.common.util.concurrent.ListeningExecutorService; @Singleton public class CloudStackComputeService extends BaseComputeService { protected final CloudStackApi client; protected final LoadingCache securityGroupMap; protected final LoadingCache keyPairCache; protected final Function, Multimap> orphanedGroupsByZoneId; protected final GroupNamingConvention.Factory namingConvention; protected final Supplier> zoneIdToZone; @Inject protected CloudStackComputeService(ComputeServiceContext context, Map credentialStore, @Memoized Supplier> images, @Memoized Supplier> sizes, @Memoized Supplier> locations, ListNodesStrategy listNodesStrategy, GetImageStrategy getImageStrategy, GetNodeMetadataStrategy getNodeMetadataStrategy, CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy, RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy, ResumeNodeStrategy startNodeStrategy, SuspendNodeStrategy stopNodeStrategy, Provider templateBuilderProvider, @Named("DEFAULT") Provider templateOptionsProvider, @Named(TIMEOUT_NODE_RUNNING) Predicate> nodeRunning, @Named(TIMEOUT_NODE_TERMINATED) Predicate> nodeTerminated, @Named(TIMEOUT_NODE_SUSPENDED) Predicate> nodeSuspended, InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory, RunScriptOnNode.Factory runScriptOnNodeFactory, InitAdminAccess initAdminAccess, PersistNodeCredentials persistNodeCredentials, @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, CloudStackApi client, LoadingCache securityGroupMap, LoadingCache keyPairCache, Function, Multimap> orphanedGroupsByZoneId, GroupNamingConvention.Factory namingConvention, Supplier> zoneIdToZone, Optional imageExtension, Optional securityGroupExtension, DelegatingImageExtension.Factory delegatingImageExtension) { super(context, credentialStore, images, sizes, locations, listNodesStrategy, getImageStrategy, getNodeMetadataStrategy, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy, startNodeStrategy, stopNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning, nodeTerminated, nodeSuspended, initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory, persistNodeCredentials, userExecutor, imageExtension, securityGroupExtension, delegatingImageExtension); this.zoneIdToZone = checkNotNull(zoneIdToZone, "zoneIdToZone"); this.client = checkNotNull(client, "client"); this.securityGroupMap = checkNotNull(securityGroupMap, "securityGroupMap"); this.keyPairCache = checkNotNull(keyPairCache, "keyPairCache"); this.orphanedGroupsByZoneId = checkNotNull(orphanedGroupsByZoneId, "orphanedGroupsByZoneId"); this.namingConvention = checkNotNull(namingConvention, "namingConvention"); } @Override protected void cleanUpIncidentalResourcesOfDeadNodes(Set deadNodes) { Multimap zoneToZoneAndGroupNames = orphanedGroupsByZoneId.apply(deadNodes); for (String zoneId : zoneToZoneAndGroupNames.keySet()) { cleanOrphanedGroupsInZone(ImmutableSet.copyOf(zoneToZoneAndGroupNames.get(zoneId)), zoneId); } } protected void cleanOrphanedGroupsInZone(Set groups, String zoneId) { cleanupOrphanedSecurityGroupsInZone(groups, zoneId); cleanupOrphanedKeyPairsInZone(groups, zoneId); } private void cleanupOrphanedSecurityGroupsInZone(Set groups, String zoneId) { Zone zone = zoneIdToZone.get().getUnchecked(zoneId); if (supportsSecurityGroups().apply(zone)) { for (String group : groups) { for (SecurityGroup securityGroup : Iterables.filter(client.getSecurityGroupApi().listSecurityGroups(), SecurityGroupPredicates.nameMatches(namingConvention.create().containsGroup(group)))) { ZoneAndName zoneAndName = ZoneAndName.fromZoneAndName(zoneId, securityGroup.getName()); logger.debug(">> deleting securityGroup(%s)", zoneAndName); client.getSecurityGroupApi().deleteSecurityGroup(securityGroup.getId()); // TODO: test this clear happens securityGroupMap.invalidate(zoneAndName); logger.debug("<< deleted securityGroup(%s)", zoneAndName); } } } } private void cleanupOrphanedKeyPairsInZone(Set groups, String zoneId) { for (String group : groups) { for (SshKeyPair pair : Iterables.filter(client.getSSHKeyPairApi().listSSHKeyPairs(), nameMatches(namingConvention.create().containsGroup(group)))) { logger.debug(">> deleting keypair(%s)", pair.getName()); client.getSSHKeyPairApi().deleteSSHKeyPair(pair.getName()); // TODO: test this clear happens keyPairCache.invalidate(pair.getName()); logger.debug("<< deleted keypair(%s)", pair.getName()); } keyPairCache.invalidate(namingConvention.create().sharedNameForGroup(group)); } } /** * returns template options, as {@link CloudStackTemplateOptions}. */ @Override public CloudStackTemplateOptions templateOptions() { return CloudStackTemplateOptions.class.cast(super.templateOptions()); } } ================================================ FILE: apis/cloudstack/src/main/java/org/jclouds/cloudstack/compute/config/CloudStackComputeServiceContextModule.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.cloudstack.compute.config; import static java.util.concurrent.TimeUnit.SECONDS; import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL; import static org.jclouds.cloudstack.config.CloudStackProperties.AUTO_GENERATE_KEYPAIRS; import static org.jclouds.util.Predicates2.retry; import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; import jakarta.inject.Named; import jakarta.inject.Singleton; import org.jclouds.cloudstack.CloudStackApi; import org.jclouds.cloudstack.compute.extensions.CloudStackImageExtension; import org.jclouds.cloudstack.compute.extensions.CloudStackSecurityGroupExtension; import org.jclouds.cloudstack.compute.functions.CloudStackSecurityGroupToSecurityGroup; import org.jclouds.cloudstack.compute.functions.IngressRuleToIpPermission; import org.jclouds.cloudstack.compute.functions.OrphanedGroupsByZoneId; import org.jclouds.cloudstack.compute.functions.ServiceOfferingToHardware; import org.jclouds.cloudstack.compute.functions.TemplateToImage; import org.jclouds.cloudstack.compute.functions.TemplateToOperatingSystem; import org.jclouds.cloudstack.compute.functions.VirtualMachineToNodeMetadata; import org.jclouds.cloudstack.compute.functions.ZoneToLocation; import org.jclouds.cloudstack.compute.loaders.CreateUniqueKeyPair; import org.jclouds.cloudstack.compute.loaders.FindSecurityGroupOrCreate; import org.jclouds.cloudstack.compute.options.CloudStackTemplateOptions; import org.jclouds.cloudstack.compute.strategy.AdvancedNetworkOptionsConverter; import org.jclouds.cloudstack.compute.strategy.BasicNetworkOptionsConverter; import org.jclouds.cloudstack.compute.strategy.CloudStackComputeServiceAdapter; import org.jclouds.cloudstack.compute.strategy.OptionsConverter; import org.jclouds.cloudstack.domain.FirewallRule; import org.jclouds.cloudstack.domain.IPForwardingRule; import org.jclouds.cloudstack.domain.IngressRule; import org.jclouds.cloudstack.domain.Network; import org.jclouds.cloudstack.domain.NetworkType; import org.jclouds.cloudstack.domain.OSType; import org.jclouds.cloudstack.domain.Project; import org.jclouds.cloudstack.domain.SecurityGroup; import org.jclouds.cloudstack.domain.ServiceOffering; import org.jclouds.cloudstack.domain.SshKeyPair; import org.jclouds.cloudstack.domain.Template; import org.jclouds.cloudstack.domain.User; import org.jclouds.cloudstack.domain.VirtualMachine; import org.jclouds.cloudstack.domain.Zone; import org.jclouds.cloudstack.domain.ZoneAndName; import org.jclouds.cloudstack.domain.ZoneSecurityGroupNamePortsCidrs; import org.jclouds.cloudstack.features.GuestOSApi; import org.jclouds.cloudstack.functions.CreateSecurityGroupIfNeeded; import org.jclouds.cloudstack.functions.GetFirewallRulesByVirtualMachine; import org.jclouds.cloudstack.functions.GetIPForwardingRulesByVirtualMachine; import org.jclouds.cloudstack.functions.StaticNATVirtualMachineInNetwork; import org.jclouds.cloudstack.functions.ZoneIdToZone; import org.jclouds.cloudstack.predicates.JobComplete; import org.jclouds.cloudstack.suppliers.GetCurrentUser; import org.jclouds.cloudstack.suppliers.NetworksForCurrentUser; import org.jclouds.cloudstack.suppliers.ProjectsForCurrentUser; import org.jclouds.cloudstack.suppliers.ZoneIdToZoneSupplier; import org.jclouds.collect.Memoized; import org.jclouds.compute.ComputeServiceAdapter; import org.jclouds.compute.config.ComputeServiceAdapterContextModule; import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.OperatingSystem; import org.jclouds.compute.extensions.ImageExtension; import org.jclouds.compute.extensions.SecurityGroupExtension; import org.jclouds.compute.options.TemplateOptions; import org.jclouds.domain.Location; import org.jclouds.net.domain.IpPermission; import org.jclouds.rest.AuthorizationException; import org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier; import com.google.common.base.Function; import com.google.common.base.MoreObjects; import com.google.common.base.Predicate; import com.google.common.base.Supplier; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; import com.google.common.collect.Multimap; import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.Provides; import com.google.inject.TypeLiteral; import com.google.inject.assistedinject.FactoryModuleBuilder; import com.google.inject.name.Names; public class CloudStackComputeServiceContextModule extends ComputeServiceAdapterContextModule { @Override protected void configure() { super.configure(); bind(new TypeLiteral>() { }).to(CloudStackComputeServiceAdapter.class); bind(new TypeLiteral>() { }).to(VirtualMachineToNodeMetadata.class); bind(new TypeLiteral>() { }).to(CloudStackSecurityGroupToSecurityGroup.class); bind(new TypeLiteral>() { }).to(IngressRuleToIpPermission.class); bind(new TypeLiteral>() { }).to(TemplateToImage.class); bind(new TypeLiteral>() { }).to(ServiceOfferingToHardware.class); bind(new TypeLiteral>() { }).to(ZoneToLocation.class); bind(TemplateOptions.class).to(CloudStackTemplateOptions.class); bind(new TypeLiteral>() { }).to(TemplateToOperatingSystem.class); install(new FactoryModuleBuilder().build(StaticNATVirtualMachineInNetwork.Factory.class)); bind(new TypeLiteral>>() { }).to(GetIPForwardingRulesByVirtualMachine.class); bind(new TypeLiteral>>() { }).to(GetFirewallRulesByVirtualMachine.class); bind(new TypeLiteral>() { }).to(ZoneIdToZone.class); bind(new TypeLiteral>() { }).to(CreateUniqueKeyPair.class); bind(new TypeLiteral>>() { }).to(ZoneIdToZoneSupplier.class); bind(new TypeLiteral>() { }).to(CreateSecurityGroupIfNeeded.class); bind(new TypeLiteral>() { }).to(FindSecurityGroupOrCreate.class); bind(new TypeLiteral, Multimap>>() { }).to(OrphanedGroupsByZoneId.class); bind(new TypeLiteral() { }).to(CloudStackImageExtension.class); bind(new TypeLiteral() { }).to(CloudStackSecurityGroupExtension.class); // to have the compute service adapter override default locations install(new LocationsFromComputeServiceAdapterModule() { }); } @Override protected TemplateOptions provideTemplateOptions(Injector injector, TemplateOptions options) { return options.as(CloudStackTemplateOptions.class) .generateKeyPair(injector.getInstance( Key.get(boolean.class, Names.named(AUTO_GENERATE_KEYPAIRS)))); } @Provides @Singleton @Memoized public final Supplier> listOSCategories(AtomicReference authException, @Named(PROPERTY_SESSION_INTERVAL) long seconds, final CloudStackApi client) { return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException, new Supplier>() { @Override public Map get() { GuestOSApi guestOSClient = client.getGuestOSApi(); return guestOSClient.listOSCategories(); } @Override public String toString() { return MoreObjects.toStringHelper(client.getGuestOSApi()).add("method", "listOSCategories").toString(); } }, seconds, TimeUnit.SECONDS); } @Provides @Singleton @Memoized public final Supplier> listOSTypes(AtomicReference authException, @Named(PROPERTY_SESSION_INTERVAL) long seconds, final CloudStackApi client) { return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException, new Supplier>() { @Override public Map get() { GuestOSApi guestOSClient = client.getGuestOSApi(); return Maps.uniqueIndex(guestOSClient.listOSTypes(), new Function() { @Override public String apply(OSType arg0) { return arg0.getId(); } }); } @Override public String toString() { return MoreObjects.toStringHelper(client.getGuestOSApi()).add("method", "listOSTypes").toString(); } }, seconds, TimeUnit.SECONDS); } @Provides @Singleton @Memoized public final Supplier> listNetworks(AtomicReference authException, @Named(PROPERTY_SESSION_INTERVAL) long seconds, final NetworksForCurrentUser networksForCurrentUser) { return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException, networksForCurrentUser, seconds, TimeUnit.SECONDS); } @Provides @Singleton @Memoized public final Supplier> listProjects(AtomicReference authException, @Named(PROPERTY_SESSION_INTERVAL) long seconds, final ProjectsForCurrentUser projectsForCurrentUser) { return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException, projectsForCurrentUser, seconds, TimeUnit.SECONDS); } @Provides @Singleton @Memoized public final Supplier getCurrentUser(AtomicReference authException, @Named(PROPERTY_SESSION_INTERVAL) long seconds, final GetCurrentUser getCurrentUser) { return MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier.create(authException, getCurrentUser, seconds, TimeUnit.SECONDS); } @Provides @Singleton protected final Predicate jobComplete(JobComplete jobComplete) { return retry(jobComplete, 1200, 1, 5, SECONDS); } @Provides @Singleton protected final LoadingCache keyPairMap( CacheLoader in) { return CacheBuilder.newBuilder().build(in); } @Provides @Singleton protected final LoadingCache securityGroupMap( CacheLoader in) { return CacheBuilder.newBuilder().build(in); } @Provides @Singleton protected final LoadingCache> getIPForwardingRulesByVirtualMachine( CacheLoader> in) { return CacheBuilder.newBuilder().build(in); } @Provides @Singleton protected final LoadingCache> getFirewallRulesByVirtualMachine( CacheLoader> getFirewallRules) { return CacheBuilder.newBuilder().build(getFirewallRules); } @Provides @Singleton public final Map optionsConverters() { return ImmutableMap.of( NetworkType.ADVANCED, new AdvancedNetworkOptionsConverter(), NetworkType.BASIC, new BasicNetworkOptionsConverter()); } } ================================================ FILE: apis/cloudstack/src/main/java/org/jclouds/cloudstack/compute/extensions/CloudStackImageExtension.java ================================================ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jclouds.cloudstack.compute.extensions; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; import static com.google.common.collect.Iterables.find; import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_IMAGE_AVAILABLE; import static org.jclouds.location.predicates.LocationPredicates.idEquals; import java.util.NoSuchElementException; import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.atomic.AtomicReference; import jakarta.annotation.Resource; import jakarta.inject.Inject; import jakarta.inject.Named; import jakarta.inject.Singleton; import org.jclouds.Constants; import org.jclouds.cloudstack.CloudStackApi; import org.jclouds.cloudstack.domain.AsyncCreateResponse; import org.jclouds.cloudstack.domain.Template; import org.jclouds.cloudstack.domain.TemplateMetadata; import org.jclouds.cloudstack.domain.VirtualMachine; import org.jclouds.cloudstack.domain.Volume; import org.jclouds.cloudstack.options.CreateTemplateOptions; import org.jclouds.cloudstack.options.ListVolumesOptions; import org.jclouds.cloudstack.strategy.BlockUntilJobCompletesAndReturnResult; import org.jclouds.collect.Memoized; import org.jclouds.compute.domain.CloneImageTemplate; import org.jclouds.compute.domain.Image; import org.jclouds.compute.domain.ImageBuilder; import org.jclouds.compute.domain.ImageTemplate; import org.jclouds.compute.domain.ImageTemplateBuilder; import org.jclouds.compute.domain.OperatingSystem; import org.jclouds.compute.extensions.ImageExtension; import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.domain.Location; import org.jclouds.logging.Logger; import com.google.common.base.Predicate; import com.google.common.base.Supplier; import com.google.common.collect.Iterables; import com.google.common.util.concurrent.Atomics; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.UncheckedTimeoutException; /** * CloudStack implementation of {@link ImageExtension} */ @Singleton public class CloudStackImageExtension implements ImageExtension { @Resource @Named(ComputeServiceConstants.COMPUTE_LOGGER) protected Logger logger = Logger.NULL; private final CloudStackApi client; private final ListeningExecutorService userExecutor; private final Supplier> locations; private final Predicate> imageAvailablePredicate; private final BlockUntilJobCompletesAndReturnResult blockUntilJobCompletesAndReturnResult; private final Predicate jobComplete; @Inject public CloudStackImageExtension(CloudStackApi client, @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, @Memoized Supplier> locations, @Named(TIMEOUT_IMAGE_AVAILABLE) Predicate> imageAvailablePredicate, BlockUntilJobCompletesAndReturnResult blockUntilJobCompletesAndReturnResult, Predicate jobComplete) { this.client = checkNotNull(client, "client"); this.userExecutor = checkNotNull(userExecutor, "userExecutor"); this.locations = checkNotNull(locations, "locations"); this.imageAvailablePredicate = checkNotNull(imageAvailablePredicate, "imageAvailablePredicate"); this.blockUntilJobCompletesAndReturnResult = checkNotNull(blockUntilJobCompletesAndReturnResult, "blockUntilJobCompletesAndReturnResult"); this.jobComplete = checkNotNull(jobComplete, "jobComplete"); } @Override public ImageTemplate buildImageTemplateFromNode(String name, String id) { VirtualMachine vm = client.getVirtualMachineApi().getVirtualMachine(id); if (vm == null) throw new NoSuchElementException("Cannot find vm with id: " + id); CloneImageTemplate template = new ImageTemplateBuilder.CloneImageTemplateBuilder().nodeId(id).name(name).build(); return template; } @Override public ListenableFuture createImage(ImageTemplate template) { checkState(template instanceof CloneImageTemplate, " cloudstack only currently supports creating images through cloning."); CloneImageTemplate cloneTemplate = (CloneImageTemplate) template; VirtualMachine vm = client.getVirtualMachineApi().getVirtualMachine(cloneTemplate.getSourceNodeId()); String stopJob = client.getVirtualMachineApi().stopVirtualMachine(vm.getId()); jobComplete.apply(stopJob); Set volumes = client.getVolumeApi().listVolumes(ListVolumesOptions.Builder.virtualMachineId(vm.getId())); Volume volume = Iterables.getOnlyElement(volumes); CreateTemplateOptions options = CreateTemplateOptions.Builder.volumeId(volume.getId()); AsyncCreateResponse templateJob = client.getTemplateApi().createTemplate(TemplateMetadata.builder() .name(cloneTemplate.getName()) .osTypeId(vm.getGuestOSId()) .displayText(cloneTemplate.getName()) .build(), options); Template newTemplate = blockUntilJobCompletesAndReturnResult.