/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.brooklyn.location.jclouds; import java.util.Map; import org.apache.brooklyn.core.config.ConfigUtils; import org.apache.brooklyn.core.location.DeprecatedKeysMappingBuilder; import org.apache.brooklyn.core.location.LocationConfigKeys; import org.apache.brooklyn.core.location.LocationPropertiesFromBrooklynProperties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.brooklyn.util.core.config.ConfigBag; import org.apache.brooklyn.util.javalang.JavaClassNames; import com.google.common.base.Splitter; import com.google.common.base.Strings; import com.google.common.collect.Iterables; import com.google.common.collect.Maps; /** * <p> * The properties to use for a jclouds location, loaded from brooklyn.properties file * </p> * * Preferred format is: * * <ul> * <li> * brooklyn.location.named.NAME.key * </li> * <li> * brooklyn.location.jclouds.PROVIDER.key * </li> * </ul> * * <p> * A number of properties are also supported, listed in the {@code JcloudsLocationConfig} * </p> * * @author andrea **/ public class JcloudsPropertiesFromBrooklynProperties extends LocationPropertiesFromBrooklynProperties { private static final Logger LOG = LoggerFactory.getLogger(JcloudsPropertiesFromBrooklynProperties.class); @SuppressWarnings("deprecation") private static final Map<String, String> DEPRECATED_JCLOUDS_KEYS_MAPPING = new DeprecatedKeysMappingBuilder(LOG) .putAll(LocationPropertiesFromBrooklynProperties.DEPRECATED_KEYS_MAPPING) .camelToHyphen(JcloudsLocation.IMAGE_ID) .camelToHyphen(JcloudsLocation.IMAGE_NAME_REGEX) .camelToHyphen(JcloudsLocation.IMAGE_DESCRIPTION_REGEX) .camelToHyphen(JcloudsLocation.HARDWARE_ID) .build(); @Override public Map<String, Object> getLocationProperties(String provider, String namedLocation, Map<String, ?> properties) { throw new UnsupportedOperationException("Instead use getJcloudsProperties(String,String,String,Map)"); } /** * @see LocationPropertiesFromBrooklynProperties#getLocationProperties(String, String, Map) */ public Map<String, Object> getJcloudsProperties(String providerOrApi, String regionOrEndpoint, String namedLocation, Map<String, ?> properties) { if(Strings.isNullOrEmpty(namedLocation) && Strings.isNullOrEmpty(providerOrApi)) { throw new IllegalArgumentException("Neither cloud provider/API nor location name have been specified correctly"); } ConfigBag jcloudsProperties = ConfigBag.newInstance(); String provider = getProviderName(providerOrApi, namedLocation, properties); // named properties are preferred over providerOrApi properties jcloudsProperties.put(LocationConfigKeys.CLOUD_PROVIDER, provider); jcloudsProperties.putAll(transformDeprecated(getGenericLocationSingleWordProperties(properties))); jcloudsProperties.putAll(transformDeprecated(getGenericJcloudsSingleWordProperties(providerOrApi, properties))); jcloudsProperties.putAll(transformDeprecated(getProviderOrApiJcloudsProperties(providerOrApi, properties))); jcloudsProperties.putAll(transformDeprecated(getRegionJcloudsProperties(providerOrApi, regionOrEndpoint, properties))); if (!Strings.isNullOrEmpty(namedLocation)) jcloudsProperties.putAll(transformDeprecated(getNamedJcloudsProperties(namedLocation, properties))); setLocalTempDir(properties, jcloudsProperties); return jcloudsProperties.getAllConfigRaw(); } protected String getProviderName(String providerOrApi, String namedLocationName, Map<String, ?> properties) { String provider = providerOrApi; if (!Strings.isNullOrEmpty(namedLocationName)) { String providerDefinition = (String) properties.get(String.format("brooklyn.location.named.%s", namedLocationName)); if (providerDefinition!=null) { String provider2 = getProviderFromDefinition(providerDefinition); if (provider==null) { // 0.7.0 25 Feb -- is this even needed? LOG.warn(JavaClassNames.niceClassAndMethod()+" NOT set with provider, inferring from locationName "+namedLocationName+" as "+provider2); provider = provider2; } else if (!provider.equals(provider2)) { // 0.7.0 25 Feb -- previously we switched to provider2 in this case, but that was wrong when // working with chains of names; not sure why this case would ever occur (apart from tests which have been changed) // 28 Mar seen this warning many times but only in cases when NOT changing is the right behaviour LOG.debug(JavaClassNames.niceClassAndMethod()+" NOT changing provider from "+provider+" to candidate "+provider2); } } } return provider; } protected String getProviderFromDefinition(String definition) { return Iterables.get(Splitter.on(":").split(definition), 1); } protected Map<String, Object> getGenericJcloudsSingleWordProperties(String providerOrApi, Map<String, ?> properties) { if (Strings.isNullOrEmpty(providerOrApi)) return Maps.newHashMap(); String deprecatedPrefix = "brooklyn.jclouds."; String preferredPrefix = "brooklyn.location.jclouds."; return getMatchingSingleWordProperties(preferredPrefix, deprecatedPrefix, properties); } protected Map<String, Object> getProviderOrApiJcloudsProperties(String providerOrApi, Map<String, ?> properties) { if (Strings.isNullOrEmpty(providerOrApi)) return Maps.newHashMap(); String preferredPrefix = String.format("brooklyn.location.jclouds.%s.", providerOrApi); String deprecatedPrefix = String.format("brooklyn.jclouds.%s.", providerOrApi); return getMatchingProperties(preferredPrefix, deprecatedPrefix, properties); } protected Map<String, Object> getRegionJcloudsProperties(String providerOrApi, String regionName, Map<String, ?> properties) { if (Strings.isNullOrEmpty(providerOrApi) || Strings.isNullOrEmpty(regionName)) return Maps.newHashMap(); String preferredPrefix = String.format("brooklyn.location.jclouds.%s@%s.", providerOrApi, regionName); String deprecatedPrefix = String.format("brooklyn.jclouds.%s@%s.", providerOrApi, regionName); return getMatchingProperties(preferredPrefix, deprecatedPrefix, properties); } protected Map<String, Object> getNamedJcloudsProperties(String locationName, Map<String, ?> properties) { if(locationName == null) return Maps.newHashMap(); String prefix = String.format("brooklyn.location.named.%s.", locationName); return ConfigUtils.filterForPrefixAndStrip(properties, prefix).asMapWithStringKeys(); } @Override protected Map<String, String> getDeprecatedKeysMapping() { return DEPRECATED_JCLOUDS_KEYS_MAPPING; } }