Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@

package com.azure.resourcemanager.appservice.implementation;

import com.azure.core.http.HttpMethod;
import com.azure.core.http.HttpRequest;
import com.azure.core.management.AzureEnvironment;
import com.azure.core.http.HttpResponse;
import com.azure.core.management.exception.ManagementException;
import com.azure.core.util.serializer.JacksonAdapter;
import com.azure.core.util.serializer.SerializerAdapter;
Expand All @@ -16,17 +14,19 @@
import com.azure.resourcemanager.appservice.models.CsmDeploymentStatus;
import com.azure.resourcemanager.appservice.models.DeployOptions;
import com.azure.resourcemanager.appservice.models.DeployType;
import com.azure.resourcemanager.appservice.models.DeploymentBuildStatus;
import com.azure.resourcemanager.appservice.models.DeploymentSlot;
import com.azure.resourcemanager.appservice.models.DeploymentSlotBase;
import com.azure.resourcemanager.appservice.models.KuduDeploymentResult;
import com.azure.resourcemanager.appservice.models.WebApp;
import com.azure.resourcemanager.resources.fluentcore.utils.ResourceManagerUtils;
import reactor.core.publisher.Mono;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.time.Duration;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicLong;

/** The implementation for DeploymentSlot. */
class DeploymentSlotImpl
Expand All @@ -37,6 +37,7 @@ class DeploymentSlotImpl
DeploymentSlot.DefinitionStages.WithCreate,
DeploymentSlotBase.Update<DeploymentSlot>>
implements DeploymentSlot, DeploymentSlot.Definition {
private static final Duration MAX_DEPLOYMENT_STATUS_TIMEOUT = Duration.ofMinutes(5);

DeploymentSlotImpl(
String name,
Expand Down Expand Up @@ -205,45 +206,47 @@ public Mono<KuduDeploymentResult> pushDeployAsync(DeployType type, File file, De
}

@Override
public DeploymentBuildStatus getDeploymentStatus(String deploymentId) {
public CsmDeploymentStatus getDeploymentStatus(String deploymentId) {
return getDeploymentStatusAsync(deploymentId).block();
}

@Override
public Mono<DeploymentBuildStatus> getDeploymentStatusAsync(String deploymentId) {
public Mono<CsmDeploymentStatus> getDeploymentStatusAsync(String deploymentId) {
// "GET" LRO is not supported in azure-core
String deploymentStatusUrl = String.format(
"%s/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Web/sites/%s/deploymentStatus/%s?api-version=%s",
AzureEnvironment.AZURE.getResourceManagerEndpoint(),
this.manager().subscriptionId(),
this.resourceGroupName(),
this.name(),
deploymentId,
this.manager().serviceClient().getApiVersion());
HttpRequest request = new HttpRequest(HttpMethod.GET, deploymentStatusUrl);
return this.manager().httpPipeline().send(request)
.flatMap(response -> {
if (response.getStatusCode() / 100 != 2) {
return Mono.error(new ManagementException("Service responds with a non-20x response.", response));
AtomicLong pollCount = new AtomicLong();
Duration pollDuration = manager().serviceClient().getDefaultPollInterval();
return this.manager().serviceClient().getWebApps()
.getProductionSiteDeploymentStatusWithResponseAsync(this.resourceGroupName(), this.name(), deploymentId)
.flatMap(fluxResponse -> {
if (pollDuration.multipliedBy(pollCount.get()).compareTo(MAX_DEPLOYMENT_STATUS_TIMEOUT) < 0) {
HttpResponse response = new HttpFluxBBResponse(fluxResponse);
if (response.getStatusCode() / 100 != 2) {
return Mono.error(new ManagementException("Service responds with a non-20x response.", response));
}
return response.getBodyAsString()
.flatMap(bodyString -> {
SerializerAdapter serializerAdapter = JacksonAdapter.createDefaultSerializerAdapter();
CsmDeploymentStatus status;
try {
status = serializerAdapter.deserialize(bodyString, CsmDeploymentStatus.class, SerializerEncoding.JSON);
} catch (IOException e) {
return Mono.error(new ManagementException("Deserialize failed for response body.", response));
}
if (status == null) {
return Mono.empty();
}
return Mono.just(status);
});
} else {
return Mono.error(new ManagementException("Timeout getting deployment status for deploymentId: " + deploymentId, null));
}
return response.getBodyAsString()
.flatMap(bodyString -> {
SerializerAdapter serializerAdapter = JacksonAdapter.createDefaultSerializerAdapter();
CsmDeploymentStatus inner;
try {
inner = serializerAdapter.deserialize(bodyString, CsmDeploymentStatus.class, SerializerEncoding.JSON);
} catch (IOException e) {
return Mono.error(new ManagementException("Deserialize failed for response body.", response));
}
if (inner == null) {
return Mono.empty();
}
DeploymentBuildStatus status = inner.status();
if (status == null) {
return Mono.empty();
}
return Mono.just(status);
});
});
}).repeatWhenEmpty(
longFlux ->
longFlux
.flatMap(
index -> {
pollCount.set(index);
return Mono.delay(ResourceManagerUtils.InternalRuntimeContext.getDelayDuration(pollDuration));
}));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.azure.resourcemanager.appservice.implementation;

import com.azure.core.http.HttpHeaders;
import com.azure.core.http.HttpResponse;
import com.azure.core.http.rest.Response;
import com.azure.core.util.FluxUtil;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.nio.ByteBuffer;
import java.nio.charset.Charset;

/** HttpResponse wrapper for {@link com.azure.core.http.rest.Response} with FluxBB body. */
public class HttpFluxBBResponse extends HttpResponse {
private final int statusCode;
private final HttpHeaders httpHeaders;
private final Response<Flux<ByteBuffer>> originResponse;

HttpFluxBBResponse(Response<Flux<ByteBuffer>> originResponse) {
super(null);
this.statusCode = originResponse.getStatusCode();
this.httpHeaders = originResponse.getHeaders();
this.originResponse = originResponse;
}

@Override
public int getStatusCode() {
return statusCode;
}

@Override
public String getHeaderValue(String s) {
return httpHeaders.getValue(s);
}

@Override
public HttpHeaders getHeaders() {
return httpHeaders;
}

@Override
public Flux<ByteBuffer> getBody() {
return originResponse.getValue();
}

@Override
public Mono<byte[]> getBodyAsByteArray() {
return FluxUtil.collectBytesInByteBufferStream(originResponse.getValue());
}

@Override
public Mono<String> getBodyAsString() {
return getBodyAsByteArray().map(String::new);
}

@Override
public Mono<String> getBodyAsString(Charset charset) {
return getBodyAsByteArray().map(bytes -> new String(bytes, charset));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@

package com.azure.resourcemanager.appservice.implementation;

import com.azure.core.http.HttpMethod;
import com.azure.core.http.HttpRequest;
import com.azure.core.management.AzureEnvironment;
import com.azure.core.http.HttpResponse;
import com.azure.core.management.exception.ManagementException;
import com.azure.core.util.serializer.JacksonAdapter;
import com.azure.core.util.serializer.SerializerAdapter;
Expand All @@ -19,7 +17,6 @@
import com.azure.resourcemanager.appservice.models.CsmDeploymentStatus;
import com.azure.resourcemanager.appservice.models.DeployOptions;
import com.azure.resourcemanager.appservice.models.DeployType;
import com.azure.resourcemanager.appservice.models.DeploymentBuildStatus;
import com.azure.resourcemanager.appservice.models.DeploymentSlots;
import com.azure.resourcemanager.appservice.models.KuduDeploymentResult;
import com.azure.resourcemanager.appservice.models.OperatingSystem;
Expand All @@ -29,13 +26,16 @@
import com.azure.resourcemanager.appservice.models.WebAppRuntimeStack;
import com.azure.resourcemanager.resources.fluentcore.model.Creatable;
import com.azure.resourcemanager.resources.fluentcore.model.Indexable;
import com.azure.resourcemanager.resources.fluentcore.utils.ResourceManagerUtils;
import reactor.core.publisher.Mono;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.time.Duration;
import java.util.HashMap;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicLong;

/** The implementation for WebApp. */
class WebAppImpl extends AppServiceBaseImpl<WebApp, WebAppImpl, WebApp.DefinitionStages.WithCreate, WebApp.Update>
Expand All @@ -46,6 +46,7 @@ class WebAppImpl extends AppServiceBaseImpl<WebApp, WebAppImpl, WebApp.Definitio
WebApp.Update,
WebApp.UpdateStages.WithCredentials,
WebApp.UpdateStages.WithStartUpCommand {
private static final Duration MAX_DEPLOYMENT_STATUS_TIMEOUT = Duration.ofMinutes(5);

private DeploymentSlots deploymentSlots;
private WebAppRuntimeStack runtimeStackOnWindowsOSToUpdate;
Expand Down Expand Up @@ -371,45 +372,47 @@ public Mono<KuduDeploymentResult> pushDeployAsync(DeployType type, File file, De
}

@Override
public DeploymentBuildStatus getDeploymentStatus(String deploymentId) {
public CsmDeploymentStatus getDeploymentStatus(String deploymentId) {
return getDeploymentStatusAsync(deploymentId).block();
}

@Override
public Mono<DeploymentBuildStatus> getDeploymentStatusAsync(String deploymentId) {
public Mono<CsmDeploymentStatus> getDeploymentStatusAsync(String deploymentId) {
// "GET" LRO is not supported in azure-core
String deploymentStatusUrl = String.format(
"%s/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Web/sites/%s/deploymentStatus/%s?api-version=%s",
AzureEnvironment.AZURE.getResourceManagerEndpoint(),
this.manager().subscriptionId(),
this.resourceGroupName(),
this.name(),
deploymentId,
this.manager().serviceClient().getApiVersion());
HttpRequest request = new HttpRequest(HttpMethod.GET, deploymentStatusUrl);
return this.manager().httpPipeline().send(request)
.flatMap(response -> {
if (response.getStatusCode() / 100 != 2) {
return Mono.error(new ManagementException("Service responds with a non-20x response.", response));
AtomicLong pollCount = new AtomicLong();
Duration pollDuration = manager().serviceClient().getDefaultPollInterval();
return this.manager().serviceClient().getWebApps()
.getProductionSiteDeploymentStatusWithResponseAsync(this.resourceGroupName(), this.name(), deploymentId)
.flatMap(fluxResponse -> {
if (pollDuration.multipliedBy(pollCount.get()).compareTo(MAX_DEPLOYMENT_STATUS_TIMEOUT) < 0) {
HttpResponse response = new HttpFluxBBResponse(fluxResponse);
if (fluxResponse.getStatusCode() / 100 != 2) {
return Mono.error(new ManagementException("Service responds with a non-20x response.", response));
}
return response.getBodyAsString()
.flatMap(bodyString -> {
SerializerAdapter serializerAdapter = JacksonAdapter.createDefaultSerializerAdapter();
CsmDeploymentStatus status;
try {
status = serializerAdapter.deserialize(bodyString, CsmDeploymentStatus.class, SerializerEncoding.JSON);
} catch (IOException e) {
return Mono.error(new ManagementException("Deserialize failed for response body.", response));
}
if (status == null) {
return Mono.empty();
}
return Mono.just(status);
});
} else {
return Mono.error(new ManagementException("Timeout getting deployment status for deploymentId: " + deploymentId, null));
}
return response.getBodyAsString()
.flatMap(bodyString -> {
SerializerAdapter serializerAdapter = JacksonAdapter.createDefaultSerializerAdapter();
CsmDeploymentStatus inner;
try {
inner = serializerAdapter.deserialize(bodyString, CsmDeploymentStatus.class, SerializerEncoding.JSON);
} catch (IOException e) {
return Mono.error(new ManagementException("Deserialize failed for response body.", response));
}
if (inner == null) {
return Mono.empty();
}
DeploymentBuildStatus status = inner.status();
if (status == null) {
return Mono.empty();
}
return Mono.just(status);
});
});
}).repeatWhenEmpty(
longFlux ->
longFlux
.flatMap(
index -> {
pollCount.set(index);
return Mono.delay(ResourceManagerUtils.InternalRuntimeContext.getDelayDuration(pollDuration));
}));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -117,13 +117,13 @@ public interface SupportsOneDeploy {
* @param deploymentId GUID of the deployment operation
* @return the production deployment status for Azure Site
*/
DeploymentBuildStatus getDeploymentStatus(String deploymentId);
CsmDeploymentStatus getDeploymentStatus(String deploymentId);

/**
* Gets the production deployment status for Azure Site.
*
* @param deploymentId GUID of the deployment operation
* @return the production deployment status for Azure Site
*/
Mono<DeploymentBuildStatus> getDeploymentStatusAsync(String deploymentId);
Mono<CsmDeploymentStatus> getDeploymentStatusAsync(String deploymentId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,16 @@

import com.azure.core.management.Region;
import com.azure.core.test.annotation.DoNotRecord;
import com.azure.resourcemanager.appservice.models.*;
import com.azure.resourcemanager.appservice.models.CsmDeploymentStatus;
import com.azure.resourcemanager.appservice.models.DeployOptions;
import com.azure.resourcemanager.appservice.models.DeployType;
import com.azure.resourcemanager.appservice.models.DeploymentBuildStatus;
import com.azure.resourcemanager.appservice.models.JavaVersion;
import com.azure.resourcemanager.appservice.models.KuduDeploymentResult;
import com.azure.resourcemanager.appservice.models.PricingTier;
import com.azure.resourcemanager.appservice.models.RuntimeStack;
import com.azure.resourcemanager.appservice.models.WebApp;
import com.azure.resourcemanager.appservice.models.WebContainer;
import com.azure.resourcemanager.resources.fluentcore.utils.ResourceManagerUtils;
import org.apache.commons.io.IOUtils;
import org.junit.jupiter.api.Assertions;
Expand Down Expand Up @@ -93,7 +102,10 @@ public void canPushDeployJar() throws Exception {
while (!DeploymentBuildStatus.RUNTIME_SUCCESSFUL.equals(buildStatus)) {
ResourceManagerUtils.sleep(Duration.ofSeconds(10));

buildStatus = webApp1.getDeploymentStatus(deploymentId);
CsmDeploymentStatus deploymentStatus = webApp1.getDeploymentStatus(deploymentId);
Assertions.assertNotNull(deploymentStatus);

buildStatus = deploymentStatus.status();
Assertions.assertNotNull(buildStatus);

if (buildStatus.toString().contains("Failed")) {
Expand Down