Function Maven Plugin prototype (#13)
1. support function deployment using FTP; 2. implement function.json generation;
This commit is contained in:
Родитель
ef1e164d9c
Коммит
28ece551c9
|
@ -1,7 +1,7 @@
|
|||
language: java
|
||||
|
||||
jdk:
|
||||
- oraclejdk7
|
||||
- oraclejdk8
|
||||
|
||||
branches:
|
||||
only:
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
This repository contains all Maven plugins for Microsoft Azure services. Complete list of all plugins are shown as below.
|
||||
|
||||
### [Azure Web Apps Maven Plugin](./webapp-maven-plugin/README.md)
|
||||
### [Azure Functions Maven Plugin](./function-maven-plugin/README.md)
|
||||
|
||||
|
||||
### Contributing
|
||||
|
|
|
@ -3,7 +3,7 @@ branches:
|
|||
- master
|
||||
|
||||
environment:
|
||||
JAVA_HOME: "C:\\Program Files\\Java\\jdk1.7.0"
|
||||
JAVA_HOME: "C:\\Program Files\\Java\\jdk1.8.0"
|
||||
PYTHON: "C:\\Python35"
|
||||
CLIENT_ID:
|
||||
secure: rSMXqU3uFoLjHUvut92UhV/DxNcC5csNr/BSw0N2UryRVhSge2tVYvz5PAHXSJla
|
||||
|
|
|
@ -5,4 +5,6 @@
|
|||
<Class name="com.microsoft.azure.maven.function.HelpMojo"/>
|
||||
<Class name="com.microsoft.azure.maven.telemetry.GetHashMac"/>
|
||||
<Bug pattern="REC_CATCH_EXCEPTION"/>
|
||||
<Bug pattern="DP_CREATE_CLASSLOADER_INSIDE_DO_PRIVILEGED"/>
|
||||
<Bug pattern="RV_RETURN_VALUE_IGNORED_BAD_PRACTICE"/>
|
||||
</FindBugsFilter>
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
<groupId>com.microsoft.azure</groupId>
|
||||
<artifactId>function-maven-plugin</artifactId>
|
||||
<version>0.1.0</version>
|
||||
<version>0.1.1</version>
|
||||
<packaging>maven-plugin</packaging>
|
||||
<name>Azure Functions Maven Plugin</name>
|
||||
<description>Maven Plugin for Azure Functions</description>
|
||||
|
@ -21,6 +21,9 @@
|
|||
<codehaus.plexus-utils.version>3.0.20</codehaus.plexus-utils.version>
|
||||
<azure.version>1.1.2</azure.version>
|
||||
<azure.ai.version>1.0.8</azure.ai.version>
|
||||
<azure.maven-lib.version>0.1.1</azure.maven-lib.version>
|
||||
<azure.function.version>1.0.0</azure.function.version>
|
||||
<reflections.version>0.9.11</reflections.version>
|
||||
<junit.version>4.12</junit.version>
|
||||
<mockito.version>2.4.0</mockito.version>
|
||||
<spring-test.version>4.1.6.RELEASE</spring-test.version>
|
||||
|
@ -83,6 +86,15 @@
|
|||
</profile>
|
||||
</profiles>
|
||||
|
||||
<!-- Use local repo to host private JAR before the official package is released -->
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>local-repo</id>
|
||||
<name>local-repo</name>
|
||||
<url>file://${project.basedir}/repo</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven</groupId>
|
||||
|
@ -129,7 +141,17 @@
|
|||
<dependency>
|
||||
<groupId>com.microsoft.azure</groupId>
|
||||
<artifactId>maven-plugin-lib</artifactId>
|
||||
<version>0.1.0</version>
|
||||
<version>${azure.maven-lib.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.microsoft.azure.serverless</groupId>
|
||||
<artifactId>azure-functions-java-core</artifactId>
|
||||
<version>${azure.function.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.reflections</groupId>
|
||||
<artifactId>reflections</artifactId>
|
||||
<version>${reflections.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- TEST -->
|
||||
|
@ -208,8 +230,8 @@
|
|||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.3</version>
|
||||
<configuration>
|
||||
<source>1.7</source>
|
||||
<target>1.7</target>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
|
@ -224,7 +246,6 @@
|
|||
<check/>
|
||||
<instrumentation>
|
||||
<excludes>
|
||||
<exclude>**/configuration/*.class</exclude>
|
||||
<exclude>**/HelpMojo.class</exclude>
|
||||
</excludes>
|
||||
</instrumentation>
|
||||
|
|
Двоичный файл не отображается.
|
@ -6,13 +6,23 @@
|
|||
|
||||
package com.microsoft.azure.maven.function;
|
||||
|
||||
import com.microsoft.azure.management.appservice.FunctionApp;
|
||||
import com.microsoft.azure.maven.AbstractAzureMojo;
|
||||
import org.apache.maven.model.Resource;
|
||||
import org.apache.maven.plugins.annotations.Parameter;
|
||||
|
||||
import java.util.List;
|
||||
import java.io.File;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
public abstract class AbstractFunctionMojo extends AbstractAzureMojo {
|
||||
@Parameter(defaultValue = "${project.build.finalName}", readonly = true, required = true)
|
||||
protected String finalName;
|
||||
|
||||
@Parameter(defaultValue = "${project.build.directory}", readonly = true, required = true)
|
||||
protected File buildDirectory;
|
||||
|
||||
@Parameter(defaultValue = "${project.build.outputDirectory}", readonly = true, required = true)
|
||||
protected File outputDirectory;
|
||||
|
||||
@Parameter(property = "resourceGroup", required = true)
|
||||
protected String resourceGroup;
|
||||
|
||||
|
@ -22,11 +32,13 @@ public abstract class AbstractFunctionMojo extends AbstractAzureMojo {
|
|||
@Parameter(property = "region", defaultValue = "westus")
|
||||
protected String region;
|
||||
|
||||
@Parameter(property = "functionName", required = true)
|
||||
protected String functionName;
|
||||
public String getFinalName() {
|
||||
return finalName;
|
||||
}
|
||||
|
||||
@Parameter(property = "resources")
|
||||
protected List<Resource> resources;
|
||||
public String getBuildDirectoryAbsolutePath() {
|
||||
return buildDirectory.getAbsolutePath();
|
||||
}
|
||||
|
||||
public String getResourceGroup() {
|
||||
return resourceGroup;
|
||||
|
@ -40,11 +52,19 @@ public abstract class AbstractFunctionMojo extends AbstractAzureMojo {
|
|||
return region;
|
||||
}
|
||||
|
||||
public String getFunctionName() {
|
||||
return functionName;
|
||||
public String getDeploymentStageDirectory() {
|
||||
return Paths.get(getBuildDirectoryAbsolutePath(),
|
||||
"azure-functions",
|
||||
getAppName()).toString();
|
||||
}
|
||||
|
||||
public List<Resource> getResources() {
|
||||
return resources;
|
||||
public FunctionApp getFunctionApp() {
|
||||
FunctionApp app = null;
|
||||
try {
|
||||
app = getAzureClient().appServices().functionApps().getByResourceGroup(getResourceGroup(), getAppName());
|
||||
} catch (Exception e) {
|
||||
// Swallow exception
|
||||
}
|
||||
return app;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.maven.function;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.microsoft.azure.maven.function.handlers.AnnotationHandler;
|
||||
import com.microsoft.azure.maven.function.handlers.AnnotationHandlerImpl;
|
||||
import org.apache.maven.plugins.annotations.LifecyclePhase;
|
||||
import org.apache.maven.plugins.annotations.Mojo;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Goal which searches functions in target/classes directory and generates function.json files.
|
||||
*/
|
||||
@Mojo(name = "build", defaultPhase = LifecyclePhase.PACKAGE)
|
||||
public class BuildMojo extends AbstractFunctionMojo {
|
||||
|
||||
@Override
|
||||
protected void doExecute() throws Exception {
|
||||
final AnnotationHandler handler = getAnnotationHandler();
|
||||
|
||||
getLog().info("Searching for Azure Function entry points...");
|
||||
final Set<Method> functions = handler.findFunctions(getClassUrl());
|
||||
getLog().info(functions.size() + " Azure Function entry point(s) found.");
|
||||
|
||||
getLog().info("Generating Azure Function configurations...");
|
||||
final Map<String, FunctionConfiguration> configMap = handler.generateConfigurations(functions);
|
||||
final String scriptFilePath = getScriptFilePath();
|
||||
configMap.values().forEach(config -> config.setScriptFile(scriptFilePath));
|
||||
getLog().info("Generation done.");
|
||||
|
||||
getLog().info("Validating generated configurations...");
|
||||
configMap.values().forEach(config -> config.validate());
|
||||
getLog().info("Validation done.");
|
||||
|
||||
getLog().info("Saving configurations to function.json...");
|
||||
outputJsonFile(configMap);
|
||||
getLog().info("Saved successfully.");
|
||||
|
||||
getLog().info("function.json generation completed successfully.");
|
||||
}
|
||||
|
||||
protected AnnotationHandler getAnnotationHandler() throws Exception {
|
||||
return new AnnotationHandlerImpl(getLog());
|
||||
}
|
||||
|
||||
protected URL getClassUrl() throws Exception {
|
||||
return outputDirectory.toURI().toURL();
|
||||
}
|
||||
|
||||
protected String getScriptFilePath() {
|
||||
return new StringBuilder()
|
||||
.append("..\\")
|
||||
.append(getFinalName())
|
||||
.append(".jar")
|
||||
.toString();
|
||||
}
|
||||
|
||||
protected void outputJsonFile(final Map<String, FunctionConfiguration> configMap) throws IOException {
|
||||
final ObjectMapper mapper = new ObjectMapper();
|
||||
for (final Map.Entry<String, FunctionConfiguration> config : configMap.entrySet()) {
|
||||
final File file = getFunctionJsonFile(config.getKey());
|
||||
mapper.writerWithDefaultPrettyPrinter().writeValue(file, config.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
protected File getFunctionJsonFile(final String functionName) throws IOException {
|
||||
final Path functionDirPath = Paths.get(getDeploymentStageDirectory(), functionName);
|
||||
functionDirPath.toFile().mkdirs();
|
||||
final File functionJsonFile = Paths.get(functionDirPath.toString(), "function.json").toFile();
|
||||
functionJsonFile.createNewFile();
|
||||
return functionJsonFile;
|
||||
}
|
||||
}
|
|
@ -6,18 +6,66 @@
|
|||
|
||||
package com.microsoft.azure.maven.function;
|
||||
|
||||
import org.apache.maven.plugin.MojoExecutionException;
|
||||
import org.apache.maven.plugin.MojoFailureException;
|
||||
import com.microsoft.azure.management.appservice.FunctionApp;
|
||||
import com.microsoft.azure.maven.function.handlers.ArtifactHandler;
|
||||
import com.microsoft.azure.maven.function.handlers.FTPArtifactHandlerImpl;
|
||||
import org.apache.maven.model.Resource;
|
||||
import org.apache.maven.plugins.annotations.LifecyclePhase;
|
||||
import org.apache.maven.plugins.annotations.Mojo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Goal which deploy function to Azure.
|
||||
*/
|
||||
@Mojo(name = "deploy", defaultPhase = LifecyclePhase.DEPLOY)
|
||||
public class DeployMojo extends AbstractFunctionMojo {
|
||||
public static final String FUNCTION_DEPLOY_START = "Starting deploying to Function App ";
|
||||
public static final String FUNCTION_DEPLOY_SUCCESS = "Successfully deployed to Function App ";
|
||||
public static final String FUNCTION_APP_CREATE_START = "Specified Function App does not exist. " +
|
||||
"Creating a new Function App ...";
|
||||
public static final String FUNCTION_APP_CREATED = "Successfully created Function App ";
|
||||
|
||||
@Override
|
||||
public void execute() throws MojoExecutionException, MojoFailureException {
|
||||
super.execute();
|
||||
protected void doExecute() throws Exception {
|
||||
getLog().info(FUNCTION_DEPLOY_START + getAppName() + "...");
|
||||
|
||||
createFunctionAppIfNotExist();
|
||||
getArtifactHandler().publish(getResources());
|
||||
getFunctionApp().syncTriggers();
|
||||
|
||||
getLog().info(FUNCTION_DEPLOY_SUCCESS + getAppName());
|
||||
}
|
||||
|
||||
protected void createFunctionAppIfNotExist() {
|
||||
final FunctionApp app = getFunctionApp();
|
||||
|
||||
if (app == null) {
|
||||
getLog().info(FUNCTION_APP_CREATE_START);
|
||||
getAzureClient().appServices().functionApps()
|
||||
.define(getAppName())
|
||||
.withRegion(getRegion())
|
||||
.withNewResourceGroup(getResourceGroup())
|
||||
.create();
|
||||
getLog().info(FUNCTION_APP_CREATED + getAppName());
|
||||
}
|
||||
}
|
||||
|
||||
protected List<Resource> getResources() {
|
||||
final Resource resource = new Resource();
|
||||
resource.setDirectory(getBuildDirectoryAbsolutePath());
|
||||
resource.setTargetPath("/");
|
||||
resource.setFiltering(false);
|
||||
resource.setIncludes(Arrays.asList("*.jar"));
|
||||
|
||||
final ArrayList<Resource> resources = new ArrayList<>();
|
||||
resources.add(resource);
|
||||
return resources;
|
||||
}
|
||||
|
||||
protected ArtifactHandler getArtifactHandler() {
|
||||
return new FTPArtifactHandlerImpl(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.maven.function;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonGetter;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.microsoft.azure.maven.function.bindings.BaseBinding;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
public class FunctionConfiguration {
|
||||
public static final String MULTIPLE_TRIGGER = "Only one trigger is allowed for each Azure Function. " +
|
||||
"Multiple triggers found on method: ";
|
||||
public static final String HTTP_OUTPUT_NOT_ALLOWED = "HttpOutput binding is only allowed to use with " +
|
||||
"HttpTrigger binding. HttpOutput binding found on method: ";
|
||||
|
||||
private String scriptFile;
|
||||
|
||||
private String entryPoint;
|
||||
|
||||
private List<BaseBinding> bindings = new ArrayList<>();
|
||||
|
||||
private boolean disabled = false;
|
||||
|
||||
private boolean excluded;
|
||||
|
||||
@JsonGetter("scriptFile")
|
||||
public String getScriptFile() {
|
||||
return scriptFile;
|
||||
}
|
||||
|
||||
@JsonGetter("entryPoint")
|
||||
public String getEntryPoint() {
|
||||
return entryPoint;
|
||||
}
|
||||
|
||||
@JsonGetter("bindings")
|
||||
public List<BaseBinding> getBindings() {
|
||||
return bindings;
|
||||
}
|
||||
|
||||
@JsonGetter("disabled")
|
||||
public boolean isDisabled() {
|
||||
return disabled;
|
||||
}
|
||||
|
||||
@JsonGetter("excluded")
|
||||
public boolean isExcluded() {
|
||||
return excluded;
|
||||
}
|
||||
|
||||
public void setDisabled(boolean disabled) {
|
||||
this.disabled = disabled;
|
||||
}
|
||||
|
||||
public void setExcluded(boolean excluded) {
|
||||
this.excluded = excluded;
|
||||
}
|
||||
|
||||
public void setScriptFile(String scriptFile) {
|
||||
this.scriptFile = scriptFile;
|
||||
}
|
||||
|
||||
public void setEntryPoint(String entryPoint) {
|
||||
this.entryPoint = entryPoint;
|
||||
}
|
||||
|
||||
public void setBindings(List<BaseBinding> bindings) {
|
||||
this.bindings = bindings;
|
||||
}
|
||||
|
||||
public void validate() {
|
||||
if (getBindings().stream().filter(b -> b.getType().endsWith("Trigger")).count() > 1) {
|
||||
throw new RuntimeException(MULTIPLE_TRIGGER + getEntryPoint());
|
||||
}
|
||||
|
||||
if (getBindings().stream().noneMatch(b -> b.getType().equalsIgnoreCase("httpTrigger")) &&
|
||||
getBindings().stream().anyMatch(b -> b.getType().equalsIgnoreCase("http"))) {
|
||||
throw new RuntimeException(HTTP_OUTPUT_NOT_ALLOWED + getEntryPoint());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.maven.function.bindings;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonGetter;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
public class BaseBinding {
|
||||
protected String type = "";
|
||||
|
||||
protected String name = "";
|
||||
|
||||
protected String direction = "";
|
||||
|
||||
@JsonGetter("type")
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@JsonGetter("name")
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@JsonGetter("direction")
|
||||
public String getDirection() {
|
||||
return direction;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setDirection(String direction) {
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringBuilder().append("[ name: ")
|
||||
.append(getName())
|
||||
.append(", type: ")
|
||||
.append(getType())
|
||||
.append(", direction: ")
|
||||
.append(getDirection())
|
||||
.append(" ]")
|
||||
.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.maven.function.bindings;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonGetter;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.microsoft.azure.serverless.functions.annotation.HttpOutput;
|
||||
import com.microsoft.azure.serverless.functions.annotation.HttpTrigger;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
public class HttpBinding extends BaseBinding {
|
||||
private String route = "";
|
||||
|
||||
private String webHookType = "";
|
||||
|
||||
private String authLevel = "";
|
||||
|
||||
private String[] methods = {};
|
||||
|
||||
public HttpBinding(final HttpTrigger httpTrigger) {
|
||||
setDirection("in");
|
||||
setType("httpTrigger");
|
||||
setName(httpTrigger.name());
|
||||
|
||||
route = httpTrigger.route();
|
||||
authLevel = httpTrigger.authLevel().toString().toLowerCase(Locale.ENGLISH);
|
||||
methods = httpTrigger.methods();
|
||||
webHookType = httpTrigger.webHookType();
|
||||
}
|
||||
|
||||
public HttpBinding(final HttpOutput httpOutput) {
|
||||
setDirection("out");
|
||||
setType("http");
|
||||
setName(httpOutput.name());
|
||||
}
|
||||
|
||||
public HttpBinding() {
|
||||
setDirection("out");
|
||||
setType("http");
|
||||
setName("$return");
|
||||
}
|
||||
|
||||
@JsonGetter("route")
|
||||
public String getRoute() {
|
||||
return route;
|
||||
}
|
||||
|
||||
@JsonGetter("webHookType")
|
||||
public String getWebHookType() {
|
||||
return webHookType;
|
||||
}
|
||||
|
||||
@JsonGetter("authLevel")
|
||||
public String getAuthLevel() {
|
||||
return authLevel;
|
||||
}
|
||||
|
||||
@JsonGetter("methods")
|
||||
public String[] getMethods() {
|
||||
return methods.clone();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.maven.function.bindings;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonGetter;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.microsoft.azure.serverless.functions.annotation.QueueOutput;
|
||||
import com.microsoft.azure.serverless.functions.annotation.QueueTrigger;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
public class QueueBinding extends BaseBinding {
|
||||
private String queueName = "";
|
||||
|
||||
private String connection = "";
|
||||
|
||||
public QueueBinding(final QueueTrigger queueTrigger) {
|
||||
setDirection("in");
|
||||
setType("queueTrigger");
|
||||
setName(queueTrigger.name());
|
||||
|
||||
queueName = queueTrigger.queueName();
|
||||
connection = queueTrigger.connection();
|
||||
}
|
||||
|
||||
public QueueBinding(final QueueOutput queueOutput) {
|
||||
setDirection("out");
|
||||
setType("queue");
|
||||
setName(queueOutput.name());
|
||||
|
||||
queueName = queueOutput.queueName();
|
||||
connection = queueOutput.connection();
|
||||
}
|
||||
|
||||
@JsonGetter("queueName")
|
||||
public String getQueueName() {
|
||||
return queueName;
|
||||
}
|
||||
|
||||
@JsonGetter("connection")
|
||||
public String getConnection() {
|
||||
return connection;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.maven.function.bindings;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonGetter;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.microsoft.azure.serverless.functions.annotation.TimerTrigger;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
public class TimerBinding extends BaseBinding {
|
||||
private String schedule;
|
||||
|
||||
private boolean runOnStartup;
|
||||
|
||||
private boolean useMonitor;
|
||||
|
||||
public TimerBinding(final TimerTrigger timerTrigger) {
|
||||
setDirection("in");
|
||||
setType("timerTrigger");
|
||||
setName(timerTrigger.name());
|
||||
|
||||
schedule = timerTrigger.schedule();
|
||||
runOnStartup = timerTrigger.runOnStartup();
|
||||
useMonitor = timerTrigger.useMonitor();
|
||||
}
|
||||
|
||||
@JsonGetter("schedule")
|
||||
public String getSchedule() {
|
||||
return schedule;
|
||||
}
|
||||
|
||||
@JsonGetter("runOnStartUp")
|
||||
public boolean isRunOnStartup() {
|
||||
return runOnStartup;
|
||||
}
|
||||
|
||||
@JsonGetter("useMonitor")
|
||||
public boolean isUseMonitor() {
|
||||
return useMonitor;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.maven.function.handlers;
|
||||
|
||||
import com.microsoft.azure.maven.function.FunctionConfiguration;
|
||||
import org.reflections.Configuration;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public interface AnnotationHandler {
|
||||
Set<Method> findFunctions(final URL url);
|
||||
|
||||
Map<String, FunctionConfiguration> generateConfigurations(final Set<Method> methods) throws Exception;
|
||||
|
||||
FunctionConfiguration generateConfiguration(final Method method) throws Exception;
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.maven.function.handlers;
|
||||
|
||||
import com.microsoft.azure.maven.function.FunctionConfiguration;
|
||||
import com.microsoft.azure.maven.function.bindings.BaseBinding;
|
||||
import com.microsoft.azure.maven.function.bindings.HttpBinding;
|
||||
import com.microsoft.azure.maven.function.bindings.QueueBinding;
|
||||
import com.microsoft.azure.maven.function.bindings.TimerBinding;
|
||||
import com.microsoft.azure.serverless.functions.annotation.*;
|
||||
import org.apache.maven.plugin.logging.Log;
|
||||
import org.reflections.Reflections;
|
||||
import org.reflections.scanners.MethodAnnotationsScanner;
|
||||
import org.reflections.util.ConfigurationBuilder;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Parameter;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class AnnotationHandlerImpl implements AnnotationHandler {
|
||||
protected Log log;
|
||||
|
||||
public AnnotationHandlerImpl(final Log log) {
|
||||
this.log = log;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Method> findFunctions(final URL url) {
|
||||
return new Reflections(
|
||||
new ConfigurationBuilder()
|
||||
.addUrls(url)
|
||||
.addScanners(new MethodAnnotationsScanner())
|
||||
.addClassLoader(getClassLoader(url)))
|
||||
.getMethodsAnnotatedWith(FunctionName.class);
|
||||
}
|
||||
|
||||
protected ClassLoader getClassLoader(final URL url) {
|
||||
return new URLClassLoader(new URL[]{url}, this.getClass().getClassLoader());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, FunctionConfiguration> generateConfigurations(final Set<Method> methods) throws Exception {
|
||||
final Map<String, FunctionConfiguration> configMap = new HashMap<>();
|
||||
for (final Method method : methods) {
|
||||
final FunctionName functionAnnotation = method.getAnnotation(FunctionName.class);
|
||||
log.debug("Starting processing function : " + functionAnnotation.value());
|
||||
configMap.put(functionAnnotation.value(), generateConfiguration(method));
|
||||
}
|
||||
return configMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FunctionConfiguration generateConfiguration(final Method method) {
|
||||
final FunctionConfiguration config = new FunctionConfiguration();
|
||||
final List<BaseBinding> bindings = config.getBindings();
|
||||
|
||||
for (final Parameter param : method.getParameters()) {
|
||||
bindings.addAll(parseAnnotations(param::getAnnotations, this::parseParameterAnnotation));
|
||||
}
|
||||
|
||||
if (!method.getReturnType().equals(Void.TYPE)) {
|
||||
bindings.addAll(parseAnnotations(method::getAnnotations, this::parseMethodAnnotation));
|
||||
|
||||
if (bindings.stream().anyMatch(b -> b.getType().equalsIgnoreCase(HttpTrigger.class.getSimpleName())) &&
|
||||
bindings.stream().noneMatch(b -> b.getName().equalsIgnoreCase("$return"))) {
|
||||
bindings.add(new HttpBinding());
|
||||
}
|
||||
}
|
||||
|
||||
config.setEntryPoint(method.getDeclaringClass().getCanonicalName() + "." + method.getName());
|
||||
return config;
|
||||
}
|
||||
|
||||
protected List<BaseBinding> parseAnnotations(Supplier<Annotation[]> annotationProvider,
|
||||
Function<Annotation, BaseBinding> annotationParser) {
|
||||
final List<BaseBinding> bindings = new ArrayList<>();
|
||||
|
||||
for (final Annotation annotation : annotationProvider.get()) {
|
||||
final BaseBinding binding = annotationParser.apply(annotation);
|
||||
if (binding != null) {
|
||||
log.debug("Adding binding: " + binding.toString());
|
||||
bindings.add(binding);
|
||||
}
|
||||
}
|
||||
|
||||
return bindings;
|
||||
}
|
||||
|
||||
protected BaseBinding parseParameterAnnotation(final Annotation annotation) {
|
||||
if (annotation instanceof HttpTrigger) {
|
||||
return new HttpBinding((HttpTrigger) annotation);
|
||||
}
|
||||
if (annotation instanceof HttpOutput) {
|
||||
return new HttpBinding((HttpOutput) annotation);
|
||||
}
|
||||
if (annotation instanceof QueueTrigger) {
|
||||
return new QueueBinding((QueueTrigger) annotation);
|
||||
}
|
||||
if (annotation instanceof QueueOutput) {
|
||||
return new QueueBinding((QueueOutput) annotation);
|
||||
}
|
||||
if (annotation instanceof TimerTrigger) {
|
||||
return new TimerBinding((TimerTrigger) annotation);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected BaseBinding parseMethodAnnotation(final Annotation annotation) {
|
||||
BaseBinding ret = null;
|
||||
if (annotation instanceof HttpOutput) {
|
||||
ret = new HttpBinding((HttpOutput) annotation);
|
||||
} else if (annotation instanceof QueueOutput) {
|
||||
ret = new QueueBinding((QueueOutput) annotation);
|
||||
}
|
||||
|
||||
if (ret != null) {
|
||||
ret.setName("$return");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.maven.function.handlers;
|
||||
|
||||
import org.apache.maven.model.Resource;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ArtifactHandler {
|
||||
void publish(final List<Resource> resources) throws Exception;
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.maven.function.handlers;
|
||||
|
||||
import com.microsoft.azure.management.appservice.FunctionApp;
|
||||
import com.microsoft.azure.management.appservice.PublishingProfile;
|
||||
import com.microsoft.azure.maven.FTPUploader;
|
||||
import com.microsoft.azure.maven.Utils;
|
||||
import com.microsoft.azure.maven.function.AbstractFunctionMojo;
|
||||
import org.apache.maven.model.Resource;
|
||||
import org.apache.maven.plugin.MojoExecutionException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
public class FTPArtifactHandlerImpl implements ArtifactHandler {
|
||||
public static final String DEFAULT_FUNCTION_ROOT = "/site/wwwroot/";
|
||||
public static final int DEFAULT_MAX_RETRY_TIMES = 3;
|
||||
|
||||
private AbstractFunctionMojo mojo;
|
||||
|
||||
public FTPArtifactHandlerImpl(final AbstractFunctionMojo mojo) {
|
||||
this.mojo = mojo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publish(final List<Resource> resources) throws Exception {
|
||||
copyResourcesToStageDirectory(resources);
|
||||
uploadDirectoryToFTP();
|
||||
}
|
||||
|
||||
protected void copyResourcesToStageDirectory(final List<Resource> resources) throws IOException {
|
||||
Utils.copyResources(
|
||||
mojo.getProject(),
|
||||
mojo.getSession(),
|
||||
mojo.getMavenResourcesFiltering(),
|
||||
resources,
|
||||
mojo.getDeploymentStageDirectory());
|
||||
}
|
||||
|
||||
protected void uploadDirectoryToFTP() throws MojoExecutionException {
|
||||
final FTPUploader uploader = getUploader();
|
||||
final FunctionApp app = mojo.getFunctionApp();
|
||||
final PublishingProfile profile = app.getPublishingProfile();
|
||||
final String serverUrl = profile.ftpUrl().split("/", 2)[0];
|
||||
|
||||
uploader.uploadDirectoryWithRetries(
|
||||
serverUrl,
|
||||
profile.ftpUsername(),
|
||||
profile.ftpPassword(),
|
||||
mojo.getDeploymentStageDirectory(),
|
||||
DEFAULT_FUNCTION_ROOT,
|
||||
DEFAULT_MAX_RETRY_TIMES);
|
||||
}
|
||||
|
||||
protected FTPUploader getUploader() {
|
||||
return new FTPUploader(mojo.getLog());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.maven.function;
|
||||
|
||||
import com.microsoft.azure.maven.function.handlers.AnnotationHandler;
|
||||
import com.microsoft.azure.maven.function.handlers.AnnotationHandlerImpl;
|
||||
import org.apache.maven.plugin.testing.MojoRule;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.reflections.util.ClasspathHelper;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class BuildMojoTest {
|
||||
@Rule
|
||||
public MojoRule rule = new MojoRule() {
|
||||
@Override
|
||||
protected void before() throws Throwable {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void after() {
|
||||
}
|
||||
};
|
||||
|
||||
@Test
|
||||
public void doExecute() throws Exception {
|
||||
final BuildMojo mojo = getMojoFromPom("/pom.xml");
|
||||
assertNotNull(mojo);
|
||||
|
||||
final BuildMojo mojoSpy = spy(mojo);
|
||||
final AnnotationHandler handler = mock(AnnotationHandler.class);
|
||||
doReturn(handler).when(mojoSpy).getAnnotationHandler();
|
||||
doReturn(ClasspathHelper.forPackage("com.microsoft.azure.maven.function.handlers").toArray()[0])
|
||||
.when(mojoSpy)
|
||||
.getClassUrl();
|
||||
doReturn("..\\\\test.jar").when(mojoSpy).getScriptFilePath();
|
||||
mojoSpy.doExecute();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAnnotationHandler() throws Exception {
|
||||
final BuildMojo mojo = getMojoFromPom("/pom.xml");
|
||||
assertNotNull(mojo);
|
||||
|
||||
final AnnotationHandler handler = mojo.getAnnotationHandler();
|
||||
assertNotNull(handler);
|
||||
assertTrue(handler instanceof AnnotationHandlerImpl);
|
||||
}
|
||||
|
||||
private BuildMojo getMojoFromPom(String filename) throws Exception {
|
||||
final File pom = new File(BuildMojoTest.class.getResource(filename).toURI());
|
||||
return (BuildMojo) rule.lookupMojo("build", pom);
|
||||
}
|
||||
}
|
|
@ -6,6 +6,11 @@
|
|||
|
||||
package com.microsoft.azure.maven.function;
|
||||
|
||||
import com.microsoft.azure.management.appservice.FunctionApp;
|
||||
import com.microsoft.azure.maven.function.handlers.ArtifactHandler;
|
||||
import com.microsoft.azure.maven.function.handlers.FTPArtifactHandlerImpl;
|
||||
import org.apache.maven.model.Resource;
|
||||
import org.apache.maven.plugin.logging.Log;
|
||||
import org.apache.maven.plugin.testing.MojoRule;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
@ -13,9 +18,12 @@ import org.junit.runner.RunWith;
|
|||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class DeployMojoTest {
|
||||
|
@ -39,13 +47,40 @@ public class DeployMojoTest {
|
|||
|
||||
assertEquals("appName", mojo.getAppName());
|
||||
|
||||
assertEquals("a-function", mojo.getFunctionName());
|
||||
|
||||
assertEquals("westeurope", mojo.getRegion());
|
||||
}
|
||||
|
||||
assertEquals("function-maven-plugin", mojo.getPluginName());
|
||||
@Test
|
||||
public void doExecute() throws Exception {
|
||||
final DeployMojo mojo = getMojoFromPom("/pom.xml");
|
||||
assertNotNull(mojo);
|
||||
|
||||
assertEquals(1, mojo.getResources().size());
|
||||
final DeployMojo mojoSpy = spy(mojo);
|
||||
doCallRealMethod().when(mojoSpy).getLog();
|
||||
final ArtifactHandler handler = mock(ArtifactHandler.class);
|
||||
doReturn(handler).when(mojoSpy).getArtifactHandler();
|
||||
doCallRealMethod().when(mojoSpy).createFunctionAppIfNotExist();
|
||||
doCallRealMethod().when(mojoSpy).getAppName();
|
||||
doReturn("~/target").when(mojoSpy).getBuildDirectoryAbsolutePath();
|
||||
doCallRealMethod().when(mojoSpy).getResources();
|
||||
final FunctionApp app = mock(FunctionApp.class);
|
||||
doReturn(app).when(mojoSpy).getFunctionApp();
|
||||
|
||||
mojoSpy.doExecute();
|
||||
verify(mojoSpy, times(1)).createFunctionAppIfNotExist();
|
||||
verify(mojoSpy, times(1)).doExecute();
|
||||
verify(handler, times(1)).publish(anyList());
|
||||
verifyNoMoreInteractions(handler);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getArtifactHandler() throws Exception {
|
||||
final DeployMojo mojo = getMojoFromPom("/pom.xml");
|
||||
assertNotNull(mojo);
|
||||
|
||||
final ArtifactHandler handler = mojo.getArtifactHandler();
|
||||
assertNotNull(handler);
|
||||
assertTrue(handler instanceof FTPArtifactHandlerImpl);
|
||||
}
|
||||
|
||||
private DeployMojo getMojoFromPom(String filename) throws Exception {
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.maven.function.handlers;
|
||||
|
||||
import com.microsoft.azure.maven.function.FunctionConfiguration;
|
||||
import com.microsoft.azure.serverless.functions.annotation.*;
|
||||
import org.apache.maven.plugin.logging.Log;
|
||||
import org.junit.Test;
|
||||
import org.reflections.util.ClasspathHelper;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
public class AnnotationHandlerImplTest {
|
||||
public static final String HTTP_TRIGGER_FUNCTION = "HttpTriggerFunction";
|
||||
public static final String HTTP_TRIGGER_METHOD = "httpTriggerMethod";
|
||||
public static final String QUEUE_TRIGGER_FUNCTION = "QueueTriggerFunction";
|
||||
public static final String QUEUE_TRIGGER_METHOD = "queueTriggerMethod";
|
||||
public static final String TIMER_TRIGGER_FUNCTION = "TimerTriggerFunction";
|
||||
public static final String TIMER_TRIGGER_METHOD = "timerTriggerMethod";
|
||||
public static final String MULTI_OUTPUT_FUNCTION = "MultiOutputFunction";
|
||||
public static final String MULTI_OUTPUT_METHOD = "multipleOutput";
|
||||
|
||||
public class FunctionEntryPoints {
|
||||
@FunctionName(HTTP_TRIGGER_FUNCTION)
|
||||
public String httpTriggerMethod(@HttpTrigger(name = "req") String req) {
|
||||
return "Hello!";
|
||||
}
|
||||
|
||||
@FunctionName(MULTI_OUTPUT_FUNCTION)
|
||||
@HttpOutput(name = "$return")
|
||||
@QueueOutput(name = "$return", queueName = "qOut", connection = "conn")
|
||||
public String multipleOutput(@HttpTrigger(name = "req") String req) {
|
||||
return "Hello!";
|
||||
}
|
||||
|
||||
@FunctionName(QUEUE_TRIGGER_FUNCTION)
|
||||
public void queueTriggerMethod(@QueueTrigger(name = "in", queueName = "qIn", connection = "conn") String in,
|
||||
@QueueOutput(name = "out", queueName = "qOut", connection = "conn") String out) {
|
||||
}
|
||||
|
||||
@FunctionName(TIMER_TRIGGER_FUNCTION)
|
||||
public void timerTriggerMethod(@TimerTrigger(name = "timer", schedule = "", useMonitor = false) String timer) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findFunctions() throws Exception {
|
||||
final Log log = mock(Log.class);
|
||||
final AnnotationHandler handler = new AnnotationHandlerImpl(log);
|
||||
final Set<Method> functions = handler.findFunctions(getClassUrl());
|
||||
|
||||
assertEquals(4, functions.size());
|
||||
final List<String> methodNames = functions.stream().map(f -> f.getName()).collect(Collectors.toList());
|
||||
assertTrue(methodNames.contains(HTTP_TRIGGER_METHOD));
|
||||
assertTrue(methodNames.contains(QUEUE_TRIGGER_METHOD));
|
||||
assertTrue(methodNames.contains(TIMER_TRIGGER_METHOD));
|
||||
assertTrue(methodNames.contains(MULTI_OUTPUT_METHOD));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generateConfigurations() throws Exception {
|
||||
final Log log = mock(Log.class);
|
||||
final AnnotationHandler handler = new AnnotationHandlerImpl(log);
|
||||
final Set<Method> functions = handler.findFunctions(getClassUrl());
|
||||
final Map<String, FunctionConfiguration> configMap = handler.generateConfigurations(functions);
|
||||
configMap.values().forEach(config -> config.validate());
|
||||
|
||||
assertEquals(4, configMap.size());
|
||||
|
||||
assertTrue(configMap.containsKey(HTTP_TRIGGER_FUNCTION));
|
||||
final FunctionConfiguration httpTriggerFunctionConfig = configMap.get(HTTP_TRIGGER_FUNCTION);
|
||||
assertEquals(getFullyQualifiedMethodName(HTTP_TRIGGER_METHOD), httpTriggerFunctionConfig.getEntryPoint());
|
||||
assertFalse(httpTriggerFunctionConfig.isDisabled());
|
||||
assertEquals(2, httpTriggerFunctionConfig.getBindings().size());
|
||||
|
||||
assertTrue(configMap.containsKey(QUEUE_TRIGGER_FUNCTION));
|
||||
final FunctionConfiguration queueTriggerFunctionConfig = configMap.get(QUEUE_TRIGGER_FUNCTION);
|
||||
assertEquals(getFullyQualifiedMethodName(QUEUE_TRIGGER_METHOD), queueTriggerFunctionConfig.getEntryPoint());
|
||||
assertEquals(2, queueTriggerFunctionConfig.getBindings().size());
|
||||
|
||||
assertTrue(configMap.containsKey(TIMER_TRIGGER_FUNCTION));
|
||||
final FunctionConfiguration timerTriggerFunctionConfig = configMap.get(TIMER_TRIGGER_FUNCTION);
|
||||
assertEquals(getFullyQualifiedMethodName(TIMER_TRIGGER_METHOD), timerTriggerFunctionConfig.getEntryPoint());
|
||||
assertEquals(1, timerTriggerFunctionConfig.getBindings().size());
|
||||
|
||||
assertTrue(configMap.containsKey(MULTI_OUTPUT_FUNCTION));
|
||||
final FunctionConfiguration multiOutputFunctionConfig = configMap.get(MULTI_OUTPUT_FUNCTION);
|
||||
assertEquals(getFullyQualifiedMethodName(MULTI_OUTPUT_METHOD), multiOutputFunctionConfig.getEntryPoint());
|
||||
assertFalse(multiOutputFunctionConfig.isDisabled());
|
||||
assertEquals(3, multiOutputFunctionConfig.getBindings().size());
|
||||
}
|
||||
|
||||
private URL getClassUrl() {
|
||||
return ClasspathHelper.forPackage("com.microsoft.azure.maven.function.handlers")
|
||||
.iterator()
|
||||
.next();
|
||||
}
|
||||
|
||||
private String getFullyQualifiedMethodName(final String methodName) {
|
||||
return FunctionEntryPoints.class.getCanonicalName() + "." + methodName;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for
|
||||
* license information.
|
||||
*/
|
||||
|
||||
package com.microsoft.azure.maven.function.handlers;
|
||||
|
||||
import com.microsoft.azure.management.appservice.FunctionApp;
|
||||
import com.microsoft.azure.management.appservice.PublishingProfile;
|
||||
import com.microsoft.azure.maven.FTPUploader;
|
||||
import com.microsoft.azure.maven.function.DeployMojo;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
public class FTPArtifactHandlerImplTest {
|
||||
@Test
|
||||
public void publish() throws Exception {
|
||||
final DeployMojo mojo = mock(DeployMojo.class);
|
||||
final FTPArtifactHandlerImpl handler = new FTPArtifactHandlerImpl(mojo);
|
||||
final FTPArtifactHandlerImpl handlerSpy = spy(handler);
|
||||
doNothing().when(handlerSpy).copyResourcesToStageDirectory(null);
|
||||
doNothing().when(handlerSpy).uploadDirectoryToFTP();
|
||||
|
||||
handlerSpy.publish(null);
|
||||
verify(handlerSpy, times(1)).copyResourcesToStageDirectory(isNull());
|
||||
verify(handlerSpy, times(1)).uploadDirectoryToFTP();
|
||||
verify(handlerSpy, times(1)).publish(isNull());
|
||||
verifyNoMoreInteractions(handlerSpy);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void uploadDirectoryToFTP() throws Exception {
|
||||
final String ftpUrl = "ftp.azurewebsites.net/site/wwwroot";
|
||||
final PublishingProfile profile = mock(PublishingProfile.class);
|
||||
when(profile.ftpUrl()).thenReturn(ftpUrl);
|
||||
final FunctionApp app = mock(FunctionApp.class);
|
||||
when(app.getPublishingProfile()).thenReturn(profile);
|
||||
final DeployMojo mojo = mock(DeployMojo.class);
|
||||
when(mojo.getFunctionApp()).thenReturn(app);
|
||||
final FTPUploader uploader = mock(FTPUploader.class);
|
||||
final FTPArtifactHandlerImpl handler = new FTPArtifactHandlerImpl(mojo);
|
||||
final FTPArtifactHandlerImpl handlerSpy = spy(handler);
|
||||
doReturn(uploader).when(handlerSpy).getUploader();
|
||||
|
||||
handlerSpy.uploadDirectoryToFTP();
|
||||
verify(mojo, times(1)).getFunctionApp();
|
||||
verify(mojo, times(1)).getDeploymentStageDirectory();
|
||||
verifyNoMoreInteractions(mojo);
|
||||
verify(app, times(1)).getPublishingProfile();
|
||||
verifyNoMoreInteractions(app);
|
||||
verify(profile, times(1)).ftpUrl();
|
||||
verify(profile, times(1)).ftpUsername();
|
||||
verify(profile, times(1)).ftpPassword();
|
||||
verifyNoMoreInteractions(profile);
|
||||
verify(uploader, times(1))
|
||||
.uploadDirectoryWithRetries(anyString(), isNull(), isNull(), isNull(), anyString(), anyInt());
|
||||
verifyNoMoreInteractions(uploader);
|
||||
}
|
||||
}
|
|
@ -15,17 +15,7 @@
|
|||
</authentication>
|
||||
<resourceGroup>resourceGroupName</resourceGroup>
|
||||
<appName>appName</appName>
|
||||
<functionName>a-function</functionName>
|
||||
<region>westeurope</region>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>${baseDir}/target</directory>
|
||||
<targetPath>/</targetPath>
|
||||
<includes>
|
||||
<include>*.jar</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</resources>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
<groupId>com.microsoft.azure</groupId>
|
||||
<artifactId>maven-plugin-lib</artifactId>
|
||||
<version>0.1.0</version>
|
||||
<version>0.1.1</version>
|
||||
<packaging>jar</packaging>
|
||||
<name>Azure Maven plugin library</name>
|
||||
<description>Common library for Azure Maven Plugins</description>
|
||||
|
@ -162,6 +162,7 @@
|
|||
<check/>
|
||||
<instrumentation>
|
||||
<excludes>
|
||||
<exclude>**/AuthenticationSetting.class</exclude>
|
||||
<exclude>**/telemetry/**.class</exclude>
|
||||
</excludes>
|
||||
</instrumentation>
|
||||
|
|
|
@ -14,12 +14,15 @@ import org.apache.maven.execution.MavenSession;
|
|||
import org.apache.maven.plugin.AbstractMojo;
|
||||
import org.apache.maven.plugin.MojoExecutionException;
|
||||
import org.apache.maven.plugin.MojoFailureException;
|
||||
import org.apache.maven.plugin.descriptor.PluginDescriptor;
|
||||
import org.apache.maven.plugins.annotations.Component;
|
||||
import org.apache.maven.plugins.annotations.Parameter;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.apache.maven.settings.Settings;
|
||||
import org.apache.maven.shared.filtering.MavenResourcesFiltering;
|
||||
import org.codehaus.plexus.util.StringUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
|
||||
import static com.microsoft.azure.maven.telemetry.AppInsightsProxy.*;
|
||||
|
@ -30,6 +33,7 @@ import static com.microsoft.azure.maven.telemetry.AppInsightsProxy.*;
|
|||
public abstract class AbstractAzureMojo extends AbstractMojo
|
||||
implements TelemetryConfiguration, AuthConfiguration {
|
||||
public static final String AZURE_INIT_FAIL = "Failed to initialize Azure client object.";
|
||||
public static final String FAILURE_REASON = "failureReason";
|
||||
|
||||
@Parameter(defaultValue = "${project}", readonly = true, required = true)
|
||||
protected MavenProject project;
|
||||
|
@ -37,6 +41,9 @@ public abstract class AbstractAzureMojo extends AbstractMojo
|
|||
@Parameter(defaultValue = "${session}", readonly = true, required = true)
|
||||
protected MavenSession session;
|
||||
|
||||
@Parameter( defaultValue = "${plugin}", readonly = true, required = true )
|
||||
private PluginDescriptor plugin;
|
||||
|
||||
/**
|
||||
* The system settings for Maven. This is the instance resulting from
|
||||
* merging global and user-level settings files.
|
||||
|
@ -67,10 +74,6 @@ public abstract class AbstractAzureMojo extends AbstractMojo
|
|||
|
||||
private String installationId = GetHashMac.getHashMac();
|
||||
|
||||
private String pluginName = Utils.getValueFromPluginDescriptor("artifactId");
|
||||
|
||||
private String pluginVersion = Utils.getValueFromPluginDescriptor("version");
|
||||
|
||||
public MavenProject getProject() {
|
||||
return project;
|
||||
}
|
||||
|
@ -112,11 +115,11 @@ public abstract class AbstractAzureMojo extends AbstractMojo
|
|||
}
|
||||
|
||||
public String getPluginName() {
|
||||
return pluginName;
|
||||
return plugin.getArtifactId();
|
||||
}
|
||||
|
||||
public String getPluginVersion() {
|
||||
return pluginVersion;
|
||||
return plugin.getVersion();
|
||||
}
|
||||
|
||||
public String getUserAgent() {
|
||||
|
@ -154,12 +157,58 @@ public abstract class AbstractAzureMojo extends AbstractMojo
|
|||
|
||||
@Override
|
||||
public void execute() throws MojoExecutionException, MojoFailureException {
|
||||
if (getAzureClient() == null) {
|
||||
getTelemetryProxy().trackEvent(TelemetryEvent.INIT_FAILURE);
|
||||
throw new MojoExecutionException(AZURE_INIT_FAIL);
|
||||
try {
|
||||
if (getAzureClient() == null) {
|
||||
getTelemetryProxy().trackEvent(TelemetryEvent.INIT_FAILURE);
|
||||
throw new MojoExecutionException(AZURE_INIT_FAIL);
|
||||
} else {
|
||||
// Repopulate subscriptionId in case it is not configured.
|
||||
getTelemetryProxy().addDefaultProperty(SUBSCRIPTION_ID_KEY, getAzureClient().subscriptionId());
|
||||
}
|
||||
|
||||
trackMojoStart();
|
||||
|
||||
doExecute();
|
||||
|
||||
trackMojoSuccess();
|
||||
} catch (Exception e) {
|
||||
processException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sub-class should implement this method to do real work.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
protected abstract void doExecute() throws Exception;
|
||||
|
||||
protected void trackMojoStart() {
|
||||
getTelemetryProxy().trackEvent(this.getClass().getSimpleName() + ".start");
|
||||
}
|
||||
|
||||
protected void trackMojoSuccess() {
|
||||
getTelemetryProxy().trackEvent(this.getClass().getSimpleName() + ".success");
|
||||
}
|
||||
|
||||
protected void trackMojoFailure(final String message) {
|
||||
final HashMap<String, String> failureReason = new HashMap<>();
|
||||
failureReason.put(FAILURE_REASON, message);
|
||||
getTelemetryProxy().trackEvent(this.getClass().getSimpleName() + ".failure");
|
||||
}
|
||||
|
||||
protected void processException(final Exception exception) throws MojoExecutionException {
|
||||
final String message = exception.getMessage();
|
||||
if (StringUtils.isEmpty(message)) {
|
||||
trackMojoFailure(exception.toString());
|
||||
} else {
|
||||
// Repopulate subscriptionId in case it is not configured.
|
||||
getTelemetryProxy().addDefaultProperty(SUBSCRIPTION_ID_KEY, azure.subscriptionId());
|
||||
trackMojoFailure(message);
|
||||
}
|
||||
|
||||
if (isFailingOnError()) {
|
||||
throw new MojoExecutionException(message, exception);
|
||||
} else {
|
||||
getLog().error(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,24 +70,6 @@ public final class Utils {
|
|||
return node.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get string value from plugin descriptor file, namely /META-INF/maven/pugin.xml .
|
||||
*
|
||||
* @param tagName Valid tagName in /META-INF/maven/plugin.xml, such as "artifactId", "version" etc..
|
||||
* @return String value of target property.
|
||||
*/
|
||||
public static String getValueFromPluginDescriptor(final String tagName) {
|
||||
try (final InputStream is = Utils.class.getResourceAsStream("/META-INF/maven/plugin.xml")) {
|
||||
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
final DocumentBuilder builder = factory.newDocumentBuilder();
|
||||
final Document doc = builder.parse(is);
|
||||
doc.getDocumentElement().normalize();
|
||||
return doc.getElementsByTagName(tagName).item(0).getTextContent();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy resources to target directory using Maven resource filtering so that we don't have to handle
|
||||
* recursive directory listing and pattern matching.
|
||||
|
|
|
@ -7,7 +7,10 @@
|
|||
package com.microsoft.azure.maven;
|
||||
|
||||
import com.microsoft.azure.management.Azure;
|
||||
import com.microsoft.azure.maven.telemetry.TelemetryProxy;
|
||||
import org.apache.maven.plugin.descriptor.PluginDescriptor;
|
||||
import org.apache.maven.settings.Settings;
|
||||
import org.codehaus.plexus.util.StringUtils;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
@ -18,42 +21,83 @@ import org.mockito.junit.MockitoJUnitRunner;
|
|||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class AbstractAzureMojoTest {
|
||||
public static final String PLUGIN_NAME = "maven-plugin-lib";
|
||||
public static final String PLUGIN_VERSION = "0.1.0-SNAPSHOT";
|
||||
|
||||
@Mock
|
||||
Settings settings;
|
||||
|
||||
@Mock
|
||||
PluginDescriptor plugin;
|
||||
|
||||
@Mock
|
||||
Azure azure;
|
||||
|
||||
@Mock
|
||||
TelemetryProxy telemetryProxy;
|
||||
|
||||
@InjectMocks
|
||||
private AbstractAzureMojo mojo = new AbstractAzureMojo() {
|
||||
public String getPluginName() {
|
||||
return "maven-plugin-lib";
|
||||
public boolean isFailingOnError() {
|
||||
return true;
|
||||
}
|
||||
public String getPluginVersion() {
|
||||
return "0.1.0-SNAPSHOT";
|
||||
|
||||
@Override
|
||||
protected void doExecute() throws Exception {
|
||||
}
|
||||
};
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
when(plugin.getArtifactId()).thenReturn(PLUGIN_NAME);
|
||||
when(plugin.getVersion()).thenReturn(PLUGIN_VERSION);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAzureClient() throws Exception {
|
||||
public void getAzureClient() throws Exception {
|
||||
assertEquals(azure, mojo.getAzureClient());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMavenSettings() {
|
||||
public void getMavenSettings() {
|
||||
assertEquals(settings, mojo.getSettings());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitTelemetry() {
|
||||
assertNotNull(mojo.getTelemetryProxy());
|
||||
public void getTelemetryProxy() {
|
||||
assertEquals(telemetryProxy, mojo.getTelemetryProxy());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getUserAgent() {
|
||||
final String userAgent = mojo.getUserAgent();
|
||||
assertTrue(StringUtils.contains(userAgent, PLUGIN_NAME));
|
||||
assertTrue(StringUtils.contains(userAgent, PLUGIN_VERSION));
|
||||
assertTrue(StringUtils.contains(userAgent, mojo.getInstallationId()));
|
||||
assertTrue(StringUtils.contains(userAgent, mojo.getSessionId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void execute() throws Exception {
|
||||
when(azure.subscriptionId()).thenReturn("fake-subscription-id");
|
||||
mojo.execute();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void processException() throws Exception {
|
||||
final String message = "test exception message";
|
||||
String actualMessage = null;
|
||||
try {
|
||||
mojo.processException(new Exception(message));
|
||||
} catch (Exception e) {
|
||||
actualMessage = e.getMessage();
|
||||
}
|
||||
assertEquals(message, actualMessage);
|
||||
}
|
||||
}
|
||||
|
|
2
pom.xml
2
pom.xml
|
@ -4,7 +4,7 @@
|
|||
|
||||
<groupId>com.microsoft.azure</groupId>
|
||||
<artifactId>azure-maven-plugins</artifactId>
|
||||
<version>0.1.0</version>
|
||||
<version>0.1.1</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>Azure Maven Plugins</name>
|
||||
<description>Maven plugins for Microsoft Azure services</description>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
<groupId>com.microsoft.azure</groupId>
|
||||
<artifactId>webapp-maven-plugin</artifactId>
|
||||
<version>0.1.0</version>
|
||||
<version>0.1.1</version>
|
||||
<packaging>maven-plugin</packaging>
|
||||
<name>Azure Web Apps Maven Plugin</name>
|
||||
<description>Maven Plugin for Azure Web Apps</description>
|
||||
|
@ -21,6 +21,7 @@
|
|||
<codehaus.plexus-utils.version>3.0.20</codehaus.plexus-utils.version>
|
||||
<azure.version>1.1.2</azure.version>
|
||||
<azure.ai.version>1.0.8</azure.ai.version>
|
||||
<azure.maven-lib.version>0.1.1</azure.maven-lib.version>
|
||||
<junit.version>4.12</junit.version>
|
||||
<mockito.version>2.4.0</mockito.version>
|
||||
<spring-test.version>4.1.6.RELEASE</spring-test.version>
|
||||
|
@ -129,7 +130,7 @@
|
|||
<dependency>
|
||||
<groupId>com.microsoft.azure</groupId>
|
||||
<artifactId>maven-plugin-lib</artifactId>
|
||||
<version>0.1.0</version>
|
||||
<version>${azure.maven-lib.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- TEST -->
|
||||
|
|
|
@ -24,27 +24,19 @@ public class DeployMojo extends AbstractWebAppMojo {
|
|||
|
||||
public static final String WEBAPP_DEPLOY_START = "Start deploying to Web App ";
|
||||
public static final String WEBAPP_DEPLOY_SUCCESS = "Successfully deployed to Web App ";
|
||||
public static final String WEBAPP_DEPLOY_FAILURE = "Failed to deploy to Web App ";
|
||||
public static final String FAILURE_REASON = "failureReason";
|
||||
|
||||
@Override
|
||||
public void execute() throws MojoExecutionException, MojoFailureException {
|
||||
super.execute();
|
||||
protected void doExecute() throws Exception {
|
||||
getLog().info(WEBAPP_DEPLOY_START + getAppName() + APOSTROPHE);
|
||||
|
||||
try {
|
||||
logDeployStart();
|
||||
final DeployFacade facade = getDeployFacade();
|
||||
facade.setupRuntime()
|
||||
.applySettings()
|
||||
.commitChanges();
|
||||
|
||||
final DeployFacade facade = getDeployFacade();
|
||||
facade.setupRuntime()
|
||||
.applySettings()
|
||||
.commitChanges();
|
||||
facade.deployArtifacts();
|
||||
|
||||
facade.deployArtifacts();
|
||||
|
||||
logDeploySuccess();
|
||||
} catch (Exception e) {
|
||||
processException(e);
|
||||
}
|
||||
getLog().info(WEBAPP_DEPLOY_SUCCESS + getAppName());
|
||||
}
|
||||
|
||||
protected DeployFacade getDeployFacade() {
|
||||
|
@ -52,36 +44,4 @@ public class DeployMojo extends AbstractWebAppMojo {
|
|||
new DeployFacadeImplWithCreate(this) :
|
||||
new DeployFacadeImplWithUpdate(this);
|
||||
}
|
||||
|
||||
private void processException(final Exception exception) throws MojoExecutionException {
|
||||
String message = exception.getMessage();
|
||||
if (StringUtils.isEmpty(message)) {
|
||||
message = exception.toString();
|
||||
}
|
||||
logDeployFailure(message);
|
||||
|
||||
if (isFailingOnError()) {
|
||||
throw new MojoExecutionException(message, exception);
|
||||
} else {
|
||||
getLog().error(message);
|
||||
}
|
||||
}
|
||||
|
||||
private void logDeployStart() {
|
||||
getTelemetryProxy().trackEvent(TelemetryEvent.DEPLOY_START);
|
||||
getLog().info(WEBAPP_DEPLOY_START + getAppName() + APOSTROPHE);
|
||||
}
|
||||
|
||||
private void logDeploySuccess() {
|
||||
getTelemetryProxy().trackEvent(TelemetryEvent.DEPLOY_SUCCESS);
|
||||
getLog().info(WEBAPP_DEPLOY_SUCCESS + getAppName());
|
||||
}
|
||||
|
||||
private void logDeployFailure(final String message) {
|
||||
final HashMap<String, String> failureReason = new HashMap<>();
|
||||
failureReason.put(FAILURE_REASON, message);
|
||||
|
||||
getTelemetryProxy().trackEvent(TelemetryEvent.DEPLOY_FAILURE, failureReason);
|
||||
getLog().error(WEBAPP_DEPLOY_FAILURE + getAppName());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,12 +39,20 @@ public class FTPArtifactHandlerImpl implements ArtifactHandler {
|
|||
}
|
||||
|
||||
protected void uploadDirectoryToFTP() throws MojoExecutionException {
|
||||
final FTPUploader uploader = new FTPUploader(mojo.getLog());
|
||||
final FTPUploader uploader = getUploader();
|
||||
final WebApp app = mojo.getWebApp();
|
||||
final PublishingProfile profile = app.getPublishingProfile();
|
||||
final String serverUrl = profile.ftpUrl().split("/", 2)[0];
|
||||
|
||||
uploader.uploadDirectoryWithRetries(serverUrl, profile.ftpUsername(), profile.ftpPassword(),
|
||||
mojo.getDeploymentStageDirectory(), DEFAULT_WEBAPP_ROOT, DEFAULT_MAX_RETRY_TIMES);
|
||||
uploader.uploadDirectoryWithRetries(serverUrl,
|
||||
profile.ftpUsername(),
|
||||
profile.ftpPassword(),
|
||||
mojo.getDeploymentStageDirectory(),
|
||||
DEFAULT_WEBAPP_ROOT,
|
||||
DEFAULT_MAX_RETRY_TIMES);
|
||||
}
|
||||
|
||||
protected FTPUploader getUploader() {
|
||||
return new FTPUploader(mojo.getLog());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,9 @@ import com.microsoft.azure.management.appservice.JavaVersion;
|
|||
import com.microsoft.azure.management.appservice.PricingTier;
|
||||
import com.microsoft.azure.management.appservice.WebApp;
|
||||
import com.microsoft.azure.management.appservice.WebContainer;
|
||||
import com.microsoft.azure.maven.telemetry.TelemetryProxy;
|
||||
import com.microsoft.azure.maven.webapp.configuration.DeploymentType;
|
||||
import org.apache.maven.plugin.MojoExecutionException;
|
||||
import org.apache.maven.plugin.testing.MojoRule;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
|
@ -57,8 +59,6 @@ public class DeployMojoTest {
|
|||
|
||||
assertEquals(PricingTier.STANDARD_S1, mojo.getPricingTier());
|
||||
|
||||
assertEquals("webapp-maven-plugin", mojo.getPluginName());
|
||||
|
||||
assertEquals(null, mojo.getJavaVersion());
|
||||
|
||||
assertEquals(null, mojo.getJavaWebContainer());
|
||||
|
@ -109,22 +109,44 @@ public class DeployMojoTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testExecute() throws Exception {
|
||||
public void testDoExecute() throws Exception {
|
||||
final DeployMojo mojo = getMojoFromPom("/pom-linux.xml");
|
||||
assertNotNull(mojo);
|
||||
|
||||
final DeployMojo mojoSpy = spy(mojo);
|
||||
final DeployFacade facade = mock(DeployFacade.class);
|
||||
final DeployFacade facade = getDeployFacade();
|
||||
doReturn(facade).when(mojoSpy).getDeployFacade();
|
||||
final Azure azure = mock(Azure.class);
|
||||
when(azure.subscriptionId()).thenReturn("subscriptionId");
|
||||
ReflectionTestUtils.setField(mojoSpy, "azure", azure);
|
||||
doCallRealMethod().when(mojoSpy).getLog();
|
||||
|
||||
mojoSpy.execute();
|
||||
mojoSpy.doExecute();
|
||||
}
|
||||
|
||||
private DeployMojo getMojoFromPom(String filename) throws Exception {
|
||||
final File pom = new File(DeployMojoTest.class.getResource(filename).toURI());
|
||||
return (DeployMojo) rule.lookupMojo("deploy", pom);
|
||||
}
|
||||
|
||||
private DeployFacade getDeployFacade() {
|
||||
return new DeployFacade() {
|
||||
@Override
|
||||
public DeployFacade setupRuntime() throws MojoExecutionException {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeployFacade applySettings() throws MojoExecutionException {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeployFacade commitChanges() throws MojoExecutionException {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeployFacade deployArtifacts() throws Exception {
|
||||
return this;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,11 @@
|
|||
|
||||
package com.microsoft.azure.maven.webapp.handlers;
|
||||
|
||||
import com.microsoft.azure.management.appservice.PublishingProfile;
|
||||
import com.microsoft.azure.management.appservice.WebApp;
|
||||
import com.microsoft.azure.maven.FTPUploader;
|
||||
import com.microsoft.azure.maven.webapp.AbstractWebAppMojo;
|
||||
import com.microsoft.azure.maven.webapp.DeployMojo;
|
||||
import org.apache.maven.model.Resource;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
@ -51,5 +55,31 @@ public class FTPArtifactHandlerImplTest {
|
|||
|
||||
@Test
|
||||
public void uploadDirectoryToFTP() throws Exception {
|
||||
final String FTP_URL = "ftp.azurewebsites.net/site/wwwroot";
|
||||
final PublishingProfile profile = mock(PublishingProfile.class);
|
||||
when(profile.ftpUrl()).thenReturn(FTP_URL);
|
||||
final WebApp app = mock(WebApp.class);
|
||||
when(app.getPublishingProfile()).thenReturn(profile);
|
||||
final DeployMojo mojo = mock(DeployMojo.class);
|
||||
when(mojo.getWebApp()).thenReturn(app);
|
||||
final FTPUploader uploader = mock(FTPUploader.class);
|
||||
final FTPArtifactHandlerImpl handler = new FTPArtifactHandlerImpl(mojo);
|
||||
final FTPArtifactHandlerImpl handlerSpy = spy(handler);
|
||||
doReturn(uploader).when(handlerSpy).getUploader();
|
||||
|
||||
handlerSpy.uploadDirectoryToFTP();
|
||||
verify(mojo, times(1)).getWebApp();
|
||||
verify(mojo, times(1)).getDeploymentStageDirectory();
|
||||
verifyNoMoreInteractions(mojo);
|
||||
verify(app, times(1)).getPublishingProfile();
|
||||
verifyNoMoreInteractions(app);
|
||||
verify(profile, times(1)).ftpUrl();
|
||||
verify(profile, times(1)).ftpUsername();
|
||||
verify(profile, times(1)).ftpPassword();
|
||||
verifyNoMoreInteractions(profile);
|
||||
verify(uploader, times(1))
|
||||
.uploadDirectoryWithRetries(anyString(), (String) isNull(), (String) isNull(), (String) isNull(),
|
||||
anyString(), anyInt());
|
||||
verifyNoMoreInteractions(uploader);
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче