/**
* 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.management.appservice.implementation;
import com.microsoft.azure.management.apigeneration.LangDefinition;
import com.microsoft.azure.management.appservice.AppServicePlan;
import com.microsoft.azure.management.appservice.FunctionApp;
import com.microsoft.azure.management.appservice.OperatingSystem;
import com.microsoft.azure.management.appservice.PricingTier;
import com.microsoft.azure.management.appservice.SkuDescription;
import com.microsoft.azure.management.resources.fluentcore.model.Creatable;
import com.microsoft.azure.management.resources.fluentcore.model.Indexable;
import com.microsoft.azure.management.resources.fluentcore.utils.SdkContext;
import com.microsoft.azure.management.storage.SkuName;
import com.microsoft.azure.management.storage.StorageAccount;
import com.microsoft.azure.management.storage.StorageAccountKey;
import retrofit2.http.GET;
import retrofit2.http.Header;
import retrofit2.http.Headers;
import retrofit2.http.Path;
import retrofit2.http.Query;
import rx.Observable;
import rx.functions.Action0;
import rx.functions.Func1;
import java.util.List;
import java.util.Map;
/**
* The implementation for FunctionApp.
*/
@LangDefinition(ContainerName = "/Microsoft.Azure.Management.AppService.Fluent")
class FunctionAppImpl
extends AppServiceBaseImpl<FunctionApp, FunctionAppImpl, FunctionApp.DefinitionStages.WithCreate, FunctionApp.Update>
implements
FunctionApp,
FunctionApp.Definition,
FunctionApp.DefinitionStages.NewAppServicePlanWithGroup,
FunctionApp.Update {
private Creatable<StorageAccount> storageAccountCreatable;
private StorageAccount storageAccountToSet;
private StorageAccount currentStorageAccount;
private final FunctionAppKeyService functionAppKeyService;
FunctionAppImpl(String name, SiteInner innerObject, SiteConfigResourceInner configObject, AppServiceManager manager) {
super(name, innerObject, configObject, manager);
innerObject.withKind("functionapp");
functionAppKeyService = manager.restClient().retrofit().create(FunctionAppKeyService.class);
}
@Override
public FunctionAppImpl withNewConsumptionPlan() {
return withNewAppServicePlan(OperatingSystem.WINDOWS, new PricingTier("Dynamic", "Y1"));
}
@Override
public FunctionAppImpl withRuntimeVersion(String version) {
return withAppSetting("FUNCTIONS_EXTENSION_VERSION", version.startsWith("~") ? version : "~" + version);
}
@Override
public FunctionAppImpl withLatestRuntimeVersion() {
return withRuntimeVersion("latest");
}
@Override
Observable<SiteInner> submitAppSettings(final SiteInner site) {
if (storageAccountCreatable != null && createdResource(storageAccountCreatable.key()) != null) {
storageAccountToSet = (StorageAccount) createdResource(storageAccountCreatable.key());
}
if (storageAccountToSet == null) {
return super.submitAppSettings(site);
} else {
return storageAccountToSet.getKeysAsync()
.flatMapIterable(new Func1<List<StorageAccountKey>, Iterable<StorageAccountKey>>() {
@Override
public Iterable<StorageAccountKey> call(List<StorageAccountKey> storageAccountKeys) {
return storageAccountKeys;
}
})
.first().flatMap(new Func1<StorageAccountKey, Observable<SiteInner>>() {
@Override
public Observable<SiteInner> call(StorageAccountKey storageAccountKey) {
String connectionString = String.format("DefaultEndpointsProtocol=https;AccountName=%s;AccountKey=%s",
storageAccountToSet.name(), storageAccountKey.value());
withAppSetting("AzureWebJobsStorage", connectionString);
withAppSetting("AzureWebJobsDashboard", connectionString);
withAppSetting("WEBSITE_CONTENTAZUREFILECONNECTIONSTRING", connectionString);
withAppSetting("WEBSITE_CONTENTSHARE", SdkContext.randomResourceName(name(), 32));
return FunctionAppImpl.super.submitAppSettings(site);
}
}).doOnCompleted(new Action0() {
@Override
public void call() {
currentStorageAccount = storageAccountToSet;
storageAccountToSet = null;
storageAccountCreatable = null;
}
});
}
}
@Override
FunctionAppImpl withNewAppServicePlan(OperatingSystem operatingSystem, PricingTier pricingTier) {
return super.withNewAppServicePlan(operatingSystem, pricingTier).autoSetAlwaysOn(pricingTier);
}
@Override
@SuppressWarnings("unchecked")
public FunctionAppImpl withExistingAppServicePlan(AppServicePlan appServicePlan) {
super.withExistingAppServicePlan(appServicePlan);
return autoSetAlwaysOn(appServicePlan.pricingTier());
}
private FunctionAppImpl autoSetAlwaysOn(PricingTier pricingTier) {
SkuDescription description = pricingTier.toSkuDescription();
if (description.tier().equalsIgnoreCase("Basic")
|| description.tier().equalsIgnoreCase("Standard")
|| description.tier().equalsIgnoreCase("Premium")) {
return withWebAppAlwaysOn(true);
} else {
return withWebAppAlwaysOn(false);
}
}
@Override
public FunctionAppImpl withNewStorageAccount(String name, SkuName sku) {
StorageAccount.DefinitionStages.WithGroup storageDefine = manager().storageManager().storageAccounts()
.define(name)
.withRegion(regionName());
if (super.creatableGroup != null && isInCreateMode()) {
storageAccountCreatable = storageDefine.withNewResourceGroup(super.creatableGroup)
.withGeneralPurposeAccountKind()
.withSku(sku);
} else {
storageAccountCreatable = storageDefine.withExistingResourceGroup(resourceGroupName())
.withGeneralPurposeAccountKind()
.withSku(sku);
}
addCreatableDependency(storageAccountCreatable);
return this;
}
@Override
public FunctionAppImpl withExistingStorageAccount(StorageAccount storageAccount) {
this.storageAccountToSet = storageAccount;
return this;
}
@Override
public FunctionAppImpl withDailyUsageQuota(int quota) {
inner().withDailyMemoryTimeQuota(quota);
return this;
}
@Override
public FunctionAppImpl withoutDailyUsageQuota() {
return withDailyUsageQuota(0);
}
@Override
public StorageAccount storageAccount() {
return currentStorageAccount;
}
@Override
public String getMasterKey() {
return getMasterKeyAsync().toBlocking().single();
}
@Override
public Observable<String> getMasterKeyAsync() {
return functionAppKeyService.getMasterKey(resourceGroupName(), name(), manager().subscriptionId(), "2016-08-01", manager().inner().userAgent())
.map(new Func1<Map<String, String>, String>() {
@Override
public String call(Map<String, String> stringStringMap) {
return stringStringMap.get("masterKey");
}
});
}
@Override
public Observable<Indexable> createAsync() {
if (inner().serverFarmId() == null) {
withNewConsumptionPlan();
}
if (currentStorageAccount == null && storageAccountToSet == null && storageAccountCreatable == null) {
withNewStorageAccount(SdkContext.randomResourceName(name(), 20), SkuName.STANDARD_GRS);
}
return super.createAsync();
}
private interface FunctionAppKeyService {
@Headers({ "Content-Type: application/json; charset=utf-8", "x-ms-logging-context: com.microsoft.azure.management.appservice.WebApps getByResourceGroup" })
@GET("subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Web/sites/{name}/functions/admin/masterkey")
Observable<Map<String, String>> getMasterKey(@Path("resourceGroupName") String resourceGroupName, @Path("name") String name, @Path("subscriptionId") String subscriptionId, @Query("api-version") String apiVersion, @Header("User-Agent") String userAgent);
}
}