Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
outofcoffee committed Sep 20, 2016
2 parents 053a5b7 + db5e591 commit 6e5d083
Show file tree
Hide file tree
Showing 12 changed files with 156 additions and 28 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
.idea/
build/
*.iml
classes
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]
### Added
- ...

## [0.2.1] - 2016-09-20
### Added
- Adds the ability to resolve placeholder properties using a file.

## [0.2.0] - 2016-04-23
### Added
- Adds support for shared properties within declaration files, which can be reused throughout the file.
Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ The following things just happened:

Declarations also allow you to add gateways, install plugins and more. See the `examples` directory.

## Using placeholders
## Using placeholder properties

You can also use placeholders in your declaration files. This helps you reuse declaration files across different environments. For example:

Expand All @@ -110,6 +110,10 @@ You can also use placeholders in your declaration files. This helps you reuse de

./apiman apply -f simple.yml -P myApiEndpoint=http://example.com

Additionally, you can specify a properties files, containing key-value pairs, such as:

./apiman apply -f simple.yml --propertiesFile /path/to/placeholder.properties

## Shared policies and properties

To avoid repeating the same policy definitions, you can define them once in the _shared_ section of your declaration file,
Expand Down
4 changes: 3 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/

group 'io.apiman.cli'
version '0.2.0'
version '0.2.1'

buildscript {
repositories {
Expand Down Expand Up @@ -56,6 +56,7 @@ ext {
version_ducttape = '1.0.5'
version_mockito = '1.10.19'
version_restassured = '2.9.0'
version_systemrules = '1.16.0'
}

dependencies {
Expand All @@ -76,6 +77,7 @@ dependencies {
testCompile "org.rnorth.duct-tape:duct-tape:$version_ducttape"
testCompile "org.mockito:mockito-core:$version_mockito"
testCompile "com.jayway.restassured:rest-assured:$version_restassured"
testCompile "com.github.stefanbirkner:system-rules:$version_systemrules"
}

jar {
Expand Down
1 change: 1 addition & 0 deletions src/main/java/io/apiman/cli/command/AbstractCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ public void run(List<String> args) {

} catch (Exception e) {
LOGGER.error("Error in " + getCommandDescription(), e);
System.exit(1);
}

} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,15 @@
import org.kohsuke.args4j.CmdLineParser;
import org.kohsuke.args4j.Option;

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;

import static io.apiman.cli.util.Functions.of;
import static java.util.Optional.ofNullable;
Expand All @@ -68,8 +74,11 @@ public class ApplyCommand extends AbstractFinalCommand {
@Option(name = "-P", usage = "Set property (key=value)")
private List<String> properties;

@Option(name = "--propertiesFile", usage = "Properties file")
private Path propertiesFile;

@Option(name = "--serverVersion", aliases = {"-sv"}, usage = "Management API server version")
protected ManagementApiVersion serverVersion = ManagementApiVersion.DEFAULT_VERSION;
private ManagementApiVersion serverVersion = ManagementApiVersion.DEFAULT_VERSION;

@Override
protected String getCommandDescription() {
Expand All @@ -78,14 +87,37 @@ protected String getCommandDescription() {

@Override
public void performAction(CmdLineParser parser) throws CommandException {
applyDeclaration();
}

/**
* Load and then apply the Declaration.
*/
public void applyDeclaration() {
final Map<String, String> parsedProperties = BeanUtil.parseReplacements(properties);

// check for properties file
if (null != propertiesFile) {
LOGGER.trace("Loading properties file: {}", propertiesFile);

final Properties fileProperties = new Properties();
try (final InputStream propertiesIn = Files.newInputStream(propertiesFile, StandardOpenOption.READ)) {
fileProperties.load(propertiesIn);
} catch (IOException e) {
throw new CommandException(String.format("Error loading properties file: %s", propertiesFile), e);
}

fileProperties.forEach((key, value) -> parsedProperties.put((String) key, (String) value));
}

final Declaration declaration;

// parse declaration
if (declarationFile.endsWith(JSON_EXTENSION)) {
declaration = DeclarativeUtil.loadDeclaration(declarationFile, MappingUtil.JSON_MAPPER, properties);
declaration = DeclarativeUtil.loadDeclaration(declarationFile, MappingUtil.JSON_MAPPER, parsedProperties);
} else {
// default is YAML
declaration = DeclarativeUtil.loadDeclaration(declarationFile, MappingUtil.YAML_MAPPER, properties);
declaration = DeclarativeUtil.loadDeclaration(declarationFile, MappingUtil.YAML_MAPPER, parsedProperties);
}

LOGGER.info("Loaded declaration: {}", declarationFile);
Expand Down Expand Up @@ -413,6 +445,18 @@ private void performPublish(String orgName, String apiName, String apiVersion) {
ServerActionUtil.publishApi(orgName, apiName, apiVersion, serverVersion, buildServerApiClient(ActionApi.class));
}

public void setDeclarationFile(Path declarationFile) {
this.declarationFile = declarationFile;
}

public void setProperties(List<String> properties) {
this.properties = properties;
}

public void setPropertiesFile(Path propertiesFile) {
this.propertiesFile = propertiesFile;
}

public void setServerAddress(String serverAddress) {
this.serverAddress = serverAddress;
}
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/io/apiman/cli/util/AuthUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ private AuthUtil() {
}

/**
* Basic auth header.
* Authorization HTTP header.
*/
public static final String HEADER_AUTHORIZATION = "Authorization";

/**
* Scheme prefix.
* Basic Authorization scheme prefix.
*/
private static final String AUTH_BASIC = "Basic ";

Expand Down
13 changes: 6 additions & 7 deletions src/main/java/io/apiman/cli/util/DeclarativeUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package io.apiman.cli.util;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Maps;
import com.google.common.io.CharStreams;
import io.apiman.cli.core.declarative.model.Declaration;
import io.apiman.cli.core.declarative.model.SharedItems;
Expand All @@ -31,7 +32,6 @@
import java.net.HttpURLConnection;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;
Expand All @@ -56,14 +56,12 @@ public class DeclarativeUtil {
* @param properties property placeholders to resolve
* @return the Declaration
*/
public static Declaration loadDeclaration(Path path, ObjectMapper mapper, Collection<String> properties) {
final Map<String, String> parsedProperties = BeanUtil.parseReplacements(properties);

public static Declaration loadDeclaration(Path path, ObjectMapper mapper, Map<String, String> properties) {
try (InputStream is = Files.newInputStream(path)) {
String fileContents = CharStreams.toString(new InputStreamReader(is));
LOGGER.trace("Declaration file raw: {}", fileContents);

Declaration declaration = loadDeclaration(mapper, fileContents, parsedProperties);
Declaration declaration = loadDeclaration(mapper, fileContents, properties);

// check for the presence of shared properties in the declaration
final Map<String, String> sharedProperties = ofNullable(declaration.getShared())
Expand All @@ -72,10 +70,11 @@ public static Declaration loadDeclaration(Path path, ObjectMapper mapper, Collec

if (sharedProperties.size() > 0) {
LOGGER.trace("Resolving {} shared placeholders", sharedProperties.size());
parsedProperties.putAll(sharedProperties);
final Map<String, String> mutableProperties = Maps.newHashMap(properties);
mutableProperties.putAll(sharedProperties);

// this is not very efficient, as it requires parsing the declaration twice
declaration = loadDeclaration(mapper, fileContents, parsedProperties);
declaration = loadDeclaration(mapper, fileContents, mutableProperties);
}

return declaration;
Expand Down
46 changes: 46 additions & 0 deletions src/test/java/io/apiman/cli/ExceptionTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright 2016 Andrew Haines
*
* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.apiman.cli;

import io.apiman.cli.common.IntegrationTest;
import io.apiman.cli.util.AuthUtil;
import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.ExpectedSystemExit;
import org.junit.experimental.categories.Category;

/**
* @author Andrew Haines {@literal <[email protected]>}
*/
@Category(IntegrationTest.class)
public class ExceptionTest {
private static final String INVALID_URL = "this is not a valid url";

@Rule
public final ExpectedSystemExit exit = ExpectedSystemExit.none();

@Test
public void testExitWithCode1OnException() {
exit.expectSystemExitWithStatus(1);

Cli.main("gateway", "list",
"--debug",
"--server", INVALID_URL,
"--serverUsername", AuthUtil.DEFAULT_SERVER_USERNAME,
"--serverPassword", AuthUtil.DEFAULT_SERVER_PASSWORD);
}
}
25 changes: 23 additions & 2 deletions src/test/java/io/apiman/cli/command/DeclarativeTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package io.apiman.cli.command;

import com.google.common.collect.Lists;
import io.apiman.cli.common.BaseTest;
import io.apiman.cli.common.IntegrationTest;
import io.apiman.cli.core.common.model.ManagementApiVersion;
Expand All @@ -30,6 +31,7 @@

import java.nio.file.Paths;
import java.util.Collections;
import java.util.List;

/**
* Tests for {@link ApplyCommand}.
Expand Down Expand Up @@ -64,7 +66,7 @@ public void setUp() {
public void testApplyDeclaration_JustPlugins() throws Exception {
final Declaration declaration = DeclarativeUtil.loadDeclaration(
Paths.get(DeclarativeTest.class.getResource("/simple-plugin.yml").toURI()), MappingUtil.YAML_MAPPER,
Collections.emptyList());
Collections.emptyMap());

command.applyDeclaration(declaration);
}
Expand All @@ -78,8 +80,27 @@ public void testApplyDeclaration_JustPlugins() throws Exception {
public void testApplyDeclaration_Full() throws Exception {
final Declaration declaration = DeclarativeUtil.loadDeclaration(
Paths.get(DeclarativeTest.class.getResource("/simple-no-plugin.yml").toURI()), MappingUtil.YAML_MAPPER,
Collections.emptyList());
Collections.emptyMap());

command.applyDeclaration(declaration);
}

/**
* Expect that the configuration in the declaration can be applied, resolving placeholders passed
* from the command line as well as from a properties file.
*
* @throws Exception
*/
@Test
public void testApplyDeclaration_WithProperties() throws Exception {
final List<String> inlineProperties = Lists.newArrayList(
"gw.endpoint=http://example.com"
);

command.setDeclarationFile(Paths.get(DeclarativeTest.class.getResource("/simple-placeholders.yml").toURI()));
command.setProperties(inlineProperties);
command.setPropertiesFile(Paths.get(DeclarativeTest.class.getResource("/declaration-test.properties").toURI()));

command.applyDeclaration();
}
}
Loading

0 comments on commit 6e5d083

Please sign in to comment.