Initial support for HclPropertySourceLoader
This commit is contained in:
@@ -37,6 +37,11 @@
|
||||
<artifactId>consul-api</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.bertramlabs.plugins</groupId>
|
||||
<artifactId>hcl4j</artifactId>
|
||||
<version>0.3.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-consul-core</artifactId>
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.consul.hcl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.bertramlabs.plugins.hcl4j.HCLParser;
|
||||
import com.bertramlabs.plugins.hcl4j.HCLParserException;
|
||||
|
||||
import org.springframework.beans.factory.config.YamlProcessor;
|
||||
import org.springframework.boot.env.OriginTrackedMapPropertySource;
|
||||
import org.springframework.boot.env.PropertySourceLoader;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
public class HclPropertySourceLoader implements PropertySourceLoader {
|
||||
|
||||
@Override
|
||||
public String[] getFileExtensions() {
|
||||
return new String[] {"hcl"};
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PropertySource<?>> load(String name, Resource resource) throws IOException {
|
||||
Map<String, ?> properties = loadProperties(resource);
|
||||
if (properties.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return Collections
|
||||
.singletonList(new OriginTrackedMapPropertySource(name, Collections
|
||||
.unmodifiableMap(properties), true));
|
||||
|
||||
}
|
||||
|
||||
private Map<String, ?> loadProperties(Resource resource) throws IOException {
|
||||
try {
|
||||
Map<String, Object> map = new HCLParser().parse(resource.getInputStream());
|
||||
map = getFlattenedMap(map);
|
||||
return map;
|
||||
}
|
||||
catch (HCLParserException e) {
|
||||
throw new IOException("Error parsing " + resource.getFilename(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a flattened version of the given map, recursively following any nested Map
|
||||
* or Collection values. Entries from the resulting map retain the same order as the
|
||||
* source. When called with the Map from a {@link YamlProcessor.MatchCallback} the result will
|
||||
* contain the same values as the {@link YamlProcessor.MatchCallback} Properties.
|
||||
* @param source the source map
|
||||
* @return a flattened map
|
||||
* @since 4.1.3
|
||||
*/
|
||||
protected final Map<String, Object> getFlattenedMap(Map<String, Object> source) {
|
||||
Map<String, Object> result = new LinkedHashMap<>();
|
||||
buildFlattenedMap(result, source, null);
|
||||
return result;
|
||||
}
|
||||
|
||||
private void buildFlattenedMap(Map<String, Object> result, Map<String, Object> source, @Nullable String path) {
|
||||
source.forEach((key, value) -> {
|
||||
if (StringUtils.hasText(path)) {
|
||||
if (key.startsWith("[")) {
|
||||
key = path + key;
|
||||
}
|
||||
else {
|
||||
key = path + '.' + key;
|
||||
}
|
||||
}
|
||||
if (value instanceof String) {
|
||||
result.put(key, value);
|
||||
}
|
||||
else if (value instanceof Map) {
|
||||
// Need a compound key
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> map = (Map<String, Object>) value;
|
||||
buildFlattenedMap(result, map, key);
|
||||
}
|
||||
else if (value instanceof Collection) {
|
||||
// Need a compound key
|
||||
@SuppressWarnings("unchecked")
|
||||
Collection<Object> collection = (Collection<Object>) value;
|
||||
if (collection.isEmpty()) {
|
||||
result.put(key, "");
|
||||
}
|
||||
else {
|
||||
int count = 0;
|
||||
for (Object object : collection) {
|
||||
buildFlattenedMap(result, Collections.singletonMap(
|
||||
"[" + (count++) + "]", object), key);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
result.put(key, (value != null ? value : ""));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -4,3 +4,7 @@ org.springframework.cloud.consul.config.ConsulConfigAutoConfiguration
|
||||
# Bootstrap Configuration
|
||||
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
|
||||
org.springframework.cloud.consul.config.ConsulConfigBootstrapConfiguration
|
||||
|
||||
# PropertySource Loaders
|
||||
org.springframework.boot.env.PropertySourceLoader=\
|
||||
org.springframework.cloud.consul.hcl.HclPropertySourceLoader
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.consul.hcl;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@SpringBootTest(properties = { "spring.cloud.consul.config.enabled=false",
|
||||
"spring.profiles.active=hcltest" })
|
||||
public class HclPropertySourceLoaderIntegrationTests {
|
||||
|
||||
@Autowired
|
||||
Environment env;
|
||||
|
||||
@Test
|
||||
void loadProperties() throws Exception {
|
||||
assertThat(env.getProperty("variable.region.description"))
|
||||
.isEqualTo("This is the location where the Linode instance is deployed.");
|
||||
}
|
||||
|
||||
@SpringBootConfiguration
|
||||
protected static class TestConfig {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2013-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.consul.hcl;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class HclPropertySourceLoaderTests {
|
||||
|
||||
private HclPropertySourceLoader loader = new HclPropertySourceLoader();
|
||||
|
||||
@Test
|
||||
void getFileExtensions() {
|
||||
assertThat(this.loader.getFileExtensions()).isEqualTo(new String[] { "hcl" });
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadProperties() throws Exception {
|
||||
List<PropertySource<?>> loaded = this.loader.load("test.hcl",
|
||||
new ClassPathResource("test.hcl", getClass()));
|
||||
PropertySource<?> source = loaded.get(0);
|
||||
assertThat(source.getProperty("variable.region.description"))
|
||||
.isEqualTo("This is the location where the Linode instance is deployed.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
# Linode provider block. Installs Linode plugin.
|
||||
provider "linode" {
|
||||
token = "${var.token}"
|
||||
}
|
||||
|
||||
variable "region" {
|
||||
description = "This is the location where the Linode instance is deployed."
|
||||
}
|
||||
|
||||
/* A multi
|
||||
line comment. */
|
||||
resource "linode_instance" "example_linode" {
|
||||
image = "linode/ubuntu18.04"
|
||||
label = "example-linode"
|
||||
region = "${var.region}"
|
||||
type = "g6-standard-1"
|
||||
authorized_keys = [ "my-key" ]
|
||||
root_pass = "example-password"
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
# Linode provider block. Installs Linode plugin.
|
||||
provider "linode" {
|
||||
token = "${var.token}"
|
||||
}
|
||||
|
||||
variable "region" {
|
||||
description = "This is the location where the Linode instance is deployed."
|
||||
}
|
||||
|
||||
/* A multi
|
||||
line comment. */
|
||||
resource "linode_instance" "example_linode" {
|
||||
image = "linode/ubuntu18.04"
|
||||
label = "example-linode"
|
||||
region = "${var.region}"
|
||||
type = "g6-standard-1"
|
||||
authorized_keys = [ "my-key" ]
|
||||
root_pass = "example-password"
|
||||
}
|
||||
Reference in New Issue
Block a user