-
-
Notifications
You must be signed in to change notification settings - Fork 84
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[plugin-azure-functions] Introduce Azure Functions support (#1497)
- Loading branch information
Showing
18 changed files
with
606 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
= What is Azure | ||
|
||
Microsoft https://azure.microsoft.com/[Azure] is a cloud computing service created by Microsoft for building, testing, deploying, | ||
and managing applications and services through Microsoft-managed data centers. | ||
|
||
Vividus provides set of plugins to interact with the services. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
= Azure functions Plugin | ||
|
||
The plugin provides functionality to interact with https://azure.microsoft.com/en-us/services/functions/[Azure Functions] | ||
|
||
== Installation | ||
|
||
.build.gradle | ||
[source,gradle,subs="attributes+"] | ||
---- | ||
implementation(group: 'org.vividus', name: 'vividus-plugin-azure-functions', version: '{current-version}') | ||
---- | ||
|
||
== Configuration | ||
|
||
=== Authentication | ||
|
||
Authentication process relies on the configuration of environment variables. | ||
|
||
See the official https://github.com/Azure/azure-sdk-for-java/tree/master/sdk/identity/azure-identity#environment-variables["Azure identity"] guide to get more details on what types of authentication could be used. | ||
|
||
=== Azure Environment selection | ||
|
||
The Azure environment could be selected via a property: `azure.functions.environment` | ||
The default value is AZURE | ||
|
||
Possible values are: AZURE, AZURE_CHINA, AZURE_GERMANY, AZURE_US_GOVERNMENT | ||
|
||
=== Azure Subscription selection | ||
|
||
The azure subscription should be configured via `AZURE_SUBSCRIPTION_ID` environment variable | ||
|
||
== Steps | ||
|
||
=== Function triggering | ||
|
||
Triggers a function | ||
|
||
[source,gherkin] | ||
---- | ||
When I trigger funtion `$functionName` from function app `$functionAppName` in resource group `$resourceGroup` with payload:$payload and save response into $scopes variable `$variableNames` | ||
---- | ||
|
||
* `$functionName` - The name of the function to trigger | ||
* `$functionAppName` - The name of the function app | ||
* `$resourceGroup` - The resource group function relates to | ||
* `$payload` - The JSON payload to send to a function (could be empty) | ||
* `$scopes` - xref:parameters:variable-scope.adoc[The comma-separated set of the variables scopes]. | ||
* `$variableName` - The variable name to store results in JSON format. If the variable name is `my-var`, the following variables will be created: | ||
** `${my-var.body}` - The response body | ||
** `${my-var.status-code}` - The HTTP status code | ||
** `${my-var.headers}` - The response headers | ||
** `${my-var.url}` - The request URL | ||
|
||
.Trigger function | ||
[source,gherkin] | ||
---- | ||
When I trigger function `HttpTrigger1` from function app `vivdus-http-function` in resource group `vividus` with payload: | ||
and save response into scenario variable `functionTrigger` | ||
Then `${functionTrigger.status-code}` is equal to `202` | ||
---- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
project.description = 'Vividus plugin for Azure Functions' | ||
|
||
dependencies { | ||
api project(':vividus-bdd-engine') | ||
implementation project(':vividus-soft-assert') | ||
implementation project(':vividus-util') | ||
implementation(group: 'com.azure.resourcemanager', name: 'azure-resourcemanager-appservice', version: '2.2.0') | ||
implementation(group: 'com.azure', name: 'azure-identity', version: '1.3.0-beta.2') | ||
|
||
implementation(group: 'org.slf4j', name: 'slf4j-api', version: versions.slf4j) | ||
|
||
testImplementation platform(group: 'org.junit', name: 'junit-bom', version: versions.junit) | ||
testImplementation(group: 'org.junit.jupiter', name: 'junit-jupiter') | ||
testImplementation(group: 'org.mockito', name: 'mockito-junit-jupiter', version: versions.mockito) | ||
testImplementation(group: 'com.github.valfirst', name: 'slf4j-test', version: versions.slf4jTest) | ||
} | ||
|
||
tasks.artifactoryPublish.enabled = false | ||
tasks.publish.enabled = false |
57 changes: 57 additions & 0 deletions
57
...in-azure-functions/src/main/java/org/vividus/azure/functions/service/FunctionService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
/* | ||
* Copyright 2021 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.vividus.azure.functions.service; | ||
|
||
import java.util.Map; | ||
|
||
import com.azure.core.credential.TokenCredential; | ||
import com.azure.core.http.policy.HttpLogDetailLevel; | ||
import com.azure.core.management.profile.AzureProfile; | ||
import com.azure.identity.DefaultAzureCredentialBuilder; | ||
import com.azure.resourcemanager.appservice.AppServiceManager; | ||
|
||
public class FunctionService | ||
{ | ||
private final AzureProfile azureProfile; | ||
|
||
public FunctionService(AzureProfile azureProfile) | ||
{ | ||
this.azureProfile = azureProfile; | ||
} | ||
|
||
private AppServiceManager createManager(ResponseCapturingHttpPipelinePolicy responseCapturingHttpPipelinePolicy) | ||
{ | ||
TokenCredential credential = new DefaultAzureCredentialBuilder() | ||
.authorityHost(azureProfile.getEnvironment().getActiveDirectoryEndpoint()).build(); | ||
return AppServiceManager.configure() | ||
.withLogLevel(HttpLogDetailLevel.BODY_AND_HEADERS) | ||
.withPolicy(responseCapturingHttpPipelinePolicy) | ||
.authenticate(credential, azureProfile); | ||
} | ||
|
||
public Map<String, Object> triggerFunction(String resourceGroup, String appName, String functionName, | ||
Object payload) | ||
{ | ||
ResponseCapturingHttpPipelinePolicy responseCapturingHttpPipelinePolicy = | ||
new ResponseCapturingHttpPipelinePolicy(functionName); | ||
createManager(responseCapturingHttpPipelinePolicy) | ||
.functionApps() | ||
.getByResourceGroup(resourceGroup, appName) | ||
.triggerFunction(functionName, payload); | ||
return responseCapturingHttpPipelinePolicy.getResponses(); | ||
} | ||
} |
61 changes: 61 additions & 0 deletions
61
...rc/main/java/org/vividus/azure/functions/service/ResponseCapturingHttpPipelinePolicy.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
/* | ||
* Copyright 2021 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.vividus.azure.functions.service; | ||
|
||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
import com.azure.core.http.HttpPipelineCallContext; | ||
import com.azure.core.http.HttpPipelineNextPolicy; | ||
import com.azure.core.http.HttpResponse; | ||
import com.azure.core.http.policy.HttpPipelinePolicy; | ||
|
||
import reactor.core.publisher.Mono; | ||
|
||
public class ResponseCapturingHttpPipelinePolicy implements HttpPipelinePolicy | ||
{ | ||
private final Map<String, Object> recorded = new HashMap<>(); | ||
private final String funcitonName; | ||
|
||
public ResponseCapturingHttpPipelinePolicy(String funcitonName) | ||
{ | ||
this.funcitonName = funcitonName; | ||
} | ||
|
||
public Map<String, Object> getResponses() | ||
{ | ||
return new HashMap<>(recorded); | ||
} | ||
|
||
@Override | ||
public Mono<HttpResponse> process(HttpPipelineCallContext context, HttpPipelineNextPolicy next) | ||
{ | ||
return next.process().doOnSuccess(this::saveResponse); | ||
} | ||
|
||
private void saveResponse(HttpResponse response) | ||
{ | ||
String url = response.getRequest().getUrl().toString(); | ||
if (url.endsWith(funcitonName)) | ||
{ | ||
recorded.put("url", url); | ||
recorded.put("status-code", response.getStatusCode()); | ||
recorded.put("body", response.getBodyAsString()); | ||
recorded.put("headers", response.getHeaders().toMap()); | ||
} | ||
} | ||
} |
94 changes: 94 additions & 0 deletions
94
...plugin-azure-functions/src/main/java/org/vividus/azure/functions/steps/FunctionSteps.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
/* | ||
* Copyright 2021 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.vividus.azure.functions.steps; | ||
|
||
import java.util.Map; | ||
import java.util.Set; | ||
|
||
import org.apache.commons.lang3.StringUtils; | ||
import org.jbehave.core.annotations.When; | ||
import org.vividus.azure.functions.service.FunctionService; | ||
import org.vividus.bdd.context.IBddVariableContext; | ||
import org.vividus.bdd.variable.VariableScope; | ||
import org.vividus.util.json.JsonUtils; | ||
|
||
import reactor.core.publisher.Mono; | ||
|
||
public class FunctionSteps | ||
{ | ||
private final JsonUtils jsonUtils; | ||
private final FunctionService functionsService; | ||
private final IBddVariableContext bddVariableContext; | ||
|
||
public FunctionSteps(JsonUtils jsonUtils, FunctionService functionsService, IBddVariableContext bddVariableContext) | ||
{ | ||
this.jsonUtils = jsonUtils; | ||
this.functionsService = functionsService; | ||
this.bddVariableContext = bddVariableContext; | ||
} | ||
|
||
/** | ||
* Triggers Azure function by its name. And saves response from the service into variable with | ||
* a provided scope and name | ||
* @param functionApp The name of Azure Function App. The value can be retrieved by looking | ||
* at the function in the Azure Portal. | ||
* @param functionName The name of the function to execute. The value can be retrieved by looking | ||
* at the function in the Azure Portal. | ||
* @param resourceGroup Resource group name. Resource group - container that holds related resources | ||
* for an Azure solution. The value can be retrieved by looking | ||
* at the function in the Azure Portal. | ||
* @param payload the JSON that to provide to Function App function as input. | ||
* @param scopes The set (comma separated list of scopes e.g.: STORY, NEXT_BATCHES) of variables scopes<br> | ||
* <i>Available scopes:</i> | ||
* <ul> | ||
* <li><b>STEP</b> - the variable will be available only within the step, | ||
* <li><b>SCENARIO</b> - the variable will be available only within the scenario, | ||
* <li><b>STORY</b> - the variable will be available within the whole story, | ||
* <li><b>NEXT_BATCHES</b> - the variable will be available starting from next batch | ||
* </ul>scopes | ||
* @param variableName The variable name to store result. If the variable name is my-var, the following | ||
* variables will be created: | ||
* <ul> | ||
* <li>${my-var.body} - the response body</li> | ||
* <li>${my-var.status-code} - the HTTP status code is in the 200 range for a successful | ||
* request</li> | ||
* <li>${my-var.headers} - the response headers</li> | ||
* <li>${my-var.url} - the request URL</li> | ||
* </ul> | ||
*/ | ||
@SuppressWarnings("unchecked") | ||
@When("I trigger function `$functionName` from function app `$functionAppName` in resource group `$resourceGroup`" | ||
+ " with payload:$payload and save response into $scopes variable `$variableNames`") | ||
public void triggerFunction(String functionName, String functionApp, String resourceGroup, String payload, | ||
Set<VariableScope> scopes, String variableName) | ||
{ | ||
Map<String, Object> responses = functionsService.triggerFunction(resourceGroup, functionApp, functionName, | ||
convertPayload(payload)); | ||
responses.compute("body", (k, v) -> ((Mono<String>) v).block()); | ||
bddVariableContext.putVariable(scopes, variableName, responses); | ||
} | ||
|
||
@SuppressWarnings("unchecked") | ||
private Map<String, String> convertPayload(String payload) | ||
{ | ||
if (StringUtils.isBlank(payload)) | ||
{ | ||
return Map.of(); | ||
} | ||
return jsonUtils.toObject(payload, Map.class); | ||
} | ||
} |
9 changes: 9 additions & 0 deletions
9
vividus-plugin-azure-functions/src/main/resources/log4j2-vividus-azure-functions.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<Configuration> | ||
<Loggers> | ||
<Logger name="com.azure.core" level="ERROR" additivity="false"> | ||
<AppenderRef ref="console" /> | ||
<AppenderRef ref="file" /> | ||
</Logger> | ||
</Loggers> | ||
</Configuration> |
1 change: 1 addition & 0 deletions
1
vividus-plugin-azure-functions/src/main/resources/properties/defaults/default.properties
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
azure.functions.environment=AZURE |
24 changes: 24 additions & 0 deletions
24
vividus-plugin-azure-functions/src/main/resources/spring.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<beans xmlns="http://www.springframework.org/schema/beans" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util" | ||
xsi:schemaLocation=" | ||
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd | ||
http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd" | ||
default-lazy-init="true"> | ||
|
||
<bean id="functionSteps" class="org.vividus.azure.functions.steps.FunctionSteps"> | ||
<constructor-arg> | ||
<bean class="org.vividus.azure.functions.service.FunctionService"> | ||
<constructor-arg> | ||
<bean class="com.azure.core.management.profile.AzureProfile"> | ||
<constructor-arg type="com.azure.core.management.AzureEnvironment" value="${azure.functions.environment}" /> | ||
</bean> | ||
</constructor-arg> | ||
</bean> | ||
</constructor-arg> | ||
</bean> | ||
|
||
<util:list id="stepBeanNames-Azure-Function" value-type="java.lang.String"> | ||
<idref bean="functionSteps" /> | ||
</util:list> | ||
</beans> |
Oops, something went wrong.