{{key.name}} |
- {{key.value}} |
+ {{key.value}} {{'functionKeys_clickToHide' | translate}} |
{{'functionKeys_clickToShow' | translate}} |
diff --git a/AzureFunctions.AngularClient/src/app/function-keys/function-keys.component.ts b/AzureFunctions.AngularClient/src/app/function-keys/function-keys.component.ts
index a4c00686fb..565a158e73 100644
--- a/AzureFunctions.AngularClient/src/app/function-keys/function-keys.component.ts
+++ b/AzureFunctions.AngularClient/src/app/function-keys/function-keys.component.ts
@@ -1,3 +1,5 @@
+import { CacheService } from 'app/shared/services/cache.service';
+import { reachableInternalLoadBalancerApp } from 'app/shared/Utilities/internal-load-balancer';
import { Component, Input, OnChanges, OnDestroy, ViewChild, OnInit } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
@@ -37,18 +39,20 @@ export class FunctionKeysComponent implements OnChanges, OnDestroy, OnInit {
@ViewChild(BusyStateComponent) busyState: BusyStateComponent;
private functionStream: Subject ;
private functionAppStream: Subject;
- private newKeyName: string;
- private newKeyValue: string;
- private validKey: boolean;
+ public newKeyName: string;
+ public newKeyValue: string;
+ public validKey: boolean;
public keys: Array;
public addingNew: boolean;
+ public disabled = false;
constructor(
private _broadcastService: BroadcastService,
private _translateService: TranslateService,
private _utilities: UtilitiesService,
- private _aiService: AiService) {
+ private _aiService: AiService,
+ private _cacheService: CacheService) {
this.validKey = false;
this.keys = [];
@@ -58,24 +62,33 @@ export class FunctionKeysComponent implements OnChanges, OnDestroy, OnInit {
this.functionAppStream
.merge(this.functionStream)
.debounceTime(100)
- .switchMap((r: any) => {
-
+ .switchMap(r => {
const functionApp = r && (r).functionApp;
+ return reachableInternalLoadBalancerApp(functionApp || this.functionApp, this._cacheService).map(a => [r, a]);
+ })
+ .switchMap((result: [FunctionApp | FunctionInfo, boolean]) => {
+
+ const functionApp = result[0] && (result[0]).functionApp;
let fi: FunctionInfo;
if (functionApp) {
this.functionApp = functionApp;
- fi = r;
+ fi = result[0] as FunctionInfo;
}
this.setBusyState();
this.resetState();
-
- return fi
- ? this.functionApp.getFunctionKeys(fi).catch(() => Observable.of({ keys: [], links: [] }))
- : this.functionApp.getFunctionHostKeys().catch(() => Observable.of({ keys: [], links: [] }));
-
+ if (result[1]) {
+ this.disabled = false;
+ return fi
+ ? this.functionApp.getFunctionKeys(fi).catch(() => Observable.of({ keys: [], links: [] }))
+ : this.functionApp.getFunctionHostKeys().catch(() => Observable.of({ keys: [], links: [] }));
+ } else {
+ this.disabled = true;
+ return Observable.throw(this.disabled);
+ }
})
.do(null, e => {
+ this.clearBusyState();
this._aiService.trackException(e, "/errors/function-keys");
console.error(e);
})
diff --git a/AzureFunctions.AngularClient/src/app/getting-started/getting-started.component.ts b/AzureFunctions.AngularClient/src/app/getting-started/getting-started.component.ts
index 4d6042c075..ee1737100c 100644
--- a/AzureFunctions.AngularClient/src/app/getting-started/getting-started.component.ts
+++ b/AzureFunctions.AngularClient/src/app/getting-started/getting-started.component.ts
@@ -1,3 +1,4 @@
+import { ConfigService } from './../shared/services/config.service';
import { Component, Output, EventEmitter, OnInit } from '@angular/core';
import { Response, Http } from '@angular/http';
import { Observable } from 'rxjs/Observable';
@@ -57,7 +58,8 @@ export class GettingStartedComponent implements OnInit {
private _globalStateService: GlobalStateService,
private _translateService: TranslateService,
private _aiService: AiService,
- private _http: Http
+ private _http: Http,
+ private _configService: ConfigService
) {
this.isValidContainerName = true;
// http://stackoverflow.com/a/8084248/3234163
@@ -377,7 +379,7 @@ export class GettingStartedComponent implements OnInit {
appSettings: [
{ name: 'AzureWebJobsStorage', value: connectionString },
{ name: 'AzureWebJobsDashboard', value: connectionString },
- { name: Constants.runtimeVersionAppSettingName, value: Constants.runtimeVersion },
+ { name: Constants.runtimeVersionAppSettingName, value: this._configService.FunctionsVersionInfo.runtimeDefault },
{ name: 'WEBSITE_CONTENTAZUREFILECONNECTIONSTRING', value: connectionString },
{ name: 'WEBSITE_CONTENTSHARE', value: name.toLocaleLowerCase() },
{ name: `${storageAccount.name}_STORAGE`, value: connectionString },
diff --git a/AzureFunctions.AngularClient/src/app/main/main.component.html b/AzureFunctions.AngularClient/src/app/main/main.component.html
index c23ad00f30..be5da7a6b0 100644
--- a/AzureFunctions.AngularClient/src/app/main/main.component.html
+++ b/AzureFunctions.AngularClient/src/app/main/main.component.html
@@ -5,6 +5,8 @@
+
+
diff --git a/AzureFunctions.AngularClient/src/app/pop-over/pop-over.component.html b/AzureFunctions.AngularClient/src/app/pop-over/pop-over.component.html
index 13d7165c2f..e6b62f7c16 100644
--- a/AzureFunctions.AngularClient/src/app/pop-over/pop-over.component.html
+++ b/AzureFunctions.AngularClient/src/app/pop-over/pop-over.component.html
@@ -1,7 +1,7 @@
(p.name.toLowerCase() === 'code'));
if (codeIndex > -1) {
- this._code = params[codeIndex];
+ this.model.code = params[codeIndex];
params.splice(codeIndex, 1);
}
@@ -131,10 +130,6 @@ export class RunHttpComponent {
this._paramsValid = form.valid;
this.valid = this._paramsValid && this._headersValid;
this.model.queryStringParams = form.value.items;
- if (this._code) {
- this.model.queryStringParams.push(this._code);
- }
-
this.validChange.emit(this.valid);
}
diff --git a/AzureFunctions.AngularClient/src/app/shared/Utilities/internal-load-balancer.ts b/AzureFunctions.AngularClient/src/app/shared/Utilities/internal-load-balancer.ts
new file mode 100644
index 0000000000..9305e4cf72
--- /dev/null
+++ b/AzureFunctions.AngularClient/src/app/shared/Utilities/internal-load-balancer.ts
@@ -0,0 +1,25 @@
+import { FunctionApp } from './../function-app';
+import { Observable } from 'rxjs/Observable';
+import { HostingEnvironment } from './../models/arm/hosting-environment';
+import { ArmObj } from './../models/arm/arm-obj';
+import { CacheService } from 'app/shared/services/cache.service';
+
+
+export function reachableInternalLoadBalancerApp(functionApp: FunctionApp, http: CacheService): Observable {
+ if (functionApp && functionApp.site &&
+ functionApp.site.properties.hostingEnvironmentProfile &&
+ functionApp.site.properties.hostingEnvironmentProfile.id) {
+ return http.getArm(functionApp.site.properties.hostingEnvironmentProfile.id, false, '2016-09-01')
+ .mergeMap(r => {
+ const ase: ArmObj = r.json();
+ if (ase.properties.internalLoadBalancingMode &&
+ ase.properties.internalLoadBalancingMode !== 'None') {
+ return functionApp.pingScmSite();
+ } else {
+ return Observable.of(true);
+ }
+ });
+ } else {
+ return Observable.of(true);
+ }
+}
\ No newline at end of file
diff --git a/AzureFunctions.AngularClient/src/app/shared/function-app.ts b/AzureFunctions.AngularClient/src/app/shared/function-app.ts
index 1c8dba5416..0b321b7a0e 100644
--- a/AzureFunctions.AngularClient/src/app/shared/function-app.ts
+++ b/AzureFunctions.AngularClient/src/app/shared/function-app.ts
@@ -54,6 +54,7 @@ import { FunctionAppEditMode } from './models/function-app-edit-mode';
import { HostStatus } from './models/host-status';
import * as jsonschema from 'jsonschema';
+import { reachableInternalLoadBalancerApp } from '../shared/Utilities/internal-load-balancer';
export class FunctionApp {
private masterKey: string;
@@ -145,17 +146,7 @@ export class FunctionApp {
this._http = new NoCorsHttpService(_ngHttp, _broadcastService, _aiService, _translateService, () => this.getPortalHeaders());
- if (!Constants.runtimeVersion) {
- this.getLatestRuntime().subscribe((runtime: any) => {
- Constants.runtimeVersion = runtime;
- });
- }
- if (!Constants.routingExtensionVersion) {
- this._getLatestRoutingExtensionVersion().subscribe((routingVersion: any) => {
- Constants.routingExtensionVersion = routingVersion;
- });
- }
if (!_globalStateService.showTryView) {
this._userService.getStartupInfo()
@@ -245,13 +236,6 @@ export class FunctionApp {
}
}
- private _getLatestRoutingExtensionVersion() {
- return this._cacheService.get(Constants.serviceHost + 'api/latestrouting', false, this.getPortalHeaders())
- .map(r => {
- return r.json();
- })
- .retryWhen(this.retryAntares);
- }
getFunctions() {
let fcs: FunctionInfo[];
@@ -588,22 +572,25 @@ export class FunctionApp {
});
}
- let firstDone = false;
+ let queryString = '';
+ if (model.code) {
+ queryString = `?${model.code.name}=${model.code.value}`;
+ }
model.queryStringParams.forEach(p => {
const findResult = processedParams.find((pr) => {
return pr === p.name;
});
if (!findResult) {
- if (!firstDone) {
- url += '?';
- firstDone = true;
+ if (!queryString) {
+ queryString += '?';
} else {
- url += '&';
+ queryString += '&';
}
- url += p.name + '=' + p.value;
+ queryString += p.name + '=' + p.value;
}
});
+ url = url + queryString;
const inputBinding = (functionInfo.config && functionInfo.config.bindings
? functionInfo.config.bindings.find(e => e.type === 'httpTrigger')
: null);
@@ -796,7 +783,9 @@ export class FunctionApp {
}
getHostSecretsFromScm() {
- return this.getAuthSettings()
+ return reachableInternalLoadBalancerApp(this, this._cacheService)
+ .filter(i => i)
+ .mergeMap(() => this.getAuthSettings())
.mergeMap(authSettings => {
return authSettings.clientCertEnabled
? Observable.of()
@@ -1201,13 +1190,7 @@ export class FunctionApp {
@ClearCache('clearAllCachedData')
clearAllCachedData() { }
- getLatestRuntime() {
- return this._http.get(Constants.serviceHost + 'api/latestruntime', { headers: this.getPortalHeaders() })
- .map(r => {
- return r.json();
- })
- .retryWhen(this.retryAntares);
- }
+
getFunctionKeys(functionInfo: FunctionInfo, handleUnauthorized?: boolean): Observable {
handleUnauthorized = typeof handleUnauthorized !== 'undefined' ? handleUnauthorized : true;
@@ -1501,10 +1484,10 @@ export class FunctionApp {
/**
* This method just pings the root of the SCM site. It doesn't care about the response in anyway or use it.
*/
- pingScmSite() {
+ pingScmSite(): Observable {
return this._http.get(this._scmUrl, { headers: this.getScmSiteHeaders() })
- .map(_ => null)
- .catch(() => Observable.of(null));
+ .map(_ => true)
+ .catch(() => Observable.of(false));
}
private getExtensionVersion() {
diff --git a/AzureFunctions.AngularClient/src/app/shared/models/arm/hosting-environment.ts b/AzureFunctions.AngularClient/src/app/shared/models/arm/hosting-environment.ts
new file mode 100644
index 0000000000..fa8d3e1f0e
--- /dev/null
+++ b/AzureFunctions.AngularClient/src/app/shared/models/arm/hosting-environment.ts
@@ -0,0 +1,13 @@
+// App Service Environment
+
+export interface HostingEnvironmentProfile {
+ id: string;
+ name: string;
+ type: string;
+}
+
+export interface HostingEnvironment {
+ name: string;
+ internalLoadBalancingMode: 'Web' | 'None' | 'Publishing' | 'Web, Publishing' | null;
+ vnetName: string;
+}
\ No newline at end of file
diff --git a/AzureFunctions.AngularClient/src/app/shared/models/arm/site.ts b/AzureFunctions.AngularClient/src/app/shared/models/arm/site.ts
index 0f181d28f7..d9252dd901 100644
--- a/AzureFunctions.AngularClient/src/app/shared/models/arm/site.ts
+++ b/AzureFunctions.AngularClient/src/app/shared/models/arm/site.ts
@@ -1,3 +1,5 @@
+import { HostingEnvironmentProfile } from './hosting-environment';
+
export interface Site {
state: string;
hostNames: string[];
@@ -15,4 +17,5 @@ export interface Site {
siteDisabledReason?: number;
clientCertEnabled?: boolean;
clientAffinityEnabled?: boolean;
-}
+ hostingEnvironmentProfile?: HostingEnvironmentProfile;
+}
\ No newline at end of file
diff --git a/AzureFunctions.AngularClient/src/app/shared/models/constants.ts b/AzureFunctions.AngularClient/src/app/shared/models/constants.ts
index 01e00f5631..c1874754c4 100644
--- a/AzureFunctions.AngularClient/src/app/shared/models/constants.ts
+++ b/AzureFunctions.AngularClient/src/app/shared/models/constants.ts
@@ -1,4 +1,5 @@
-export class HttpMethods {
+
+export class HttpMethods {
public GET = "get";
public POST = "post";
public DELETE = "delete";
@@ -17,8 +18,6 @@ export class Constants {
? `https://${window.location.hostname}:${window.location.port}/`
: `https://${window.location.hostname}/`;
- public static runtimeVersion: string;
- public static routingExtensionVersion: string;
public static nodeVersion = '6.5.0';
public static latest = 'latest';
public static disabled = 'disabled';
@@ -86,7 +85,8 @@ export class AvailabilityStates {
export class NotificationIds {
public static alwaysOn = 'alwaysOn';
public static newRuntimeVersion = 'newRuntimeVersion';
- public static slotsHostId = "slotsBlobStorage"
+ public static slotsHostId = 'slotsBlobStorage';
+ public static runtimeV2 = 'runtimeV2';
}
export class Validations {
@@ -187,9 +187,10 @@ export class KeyCodes {
public static readonly arrowUp = 38;
public static readonly arrowRight = 39;
public static readonly arrowDown = 40;
+ public static readonly delete = 46;
}
export class DomEvents {
public static readonly keydown = 'keydown';
public static readonly click = 'click';
-}
+}
\ No newline at end of file
diff --git a/AzureFunctions.AngularClient/src/app/shared/models/http-run.ts b/AzureFunctions.AngularClient/src/app/shared/models/http-run.ts
index 202ea8cdfa..8ddebc0872 100644
--- a/AzureFunctions.AngularClient/src/app/shared/models/http-run.ts
+++ b/AzureFunctions.AngularClient/src/app/shared/models/http-run.ts
@@ -4,6 +4,7 @@
queryStringParams: Param[] = [];
headers: Param[] = [];
body: string;
+ code: Param;
constructor() {
}
diff --git a/AzureFunctions.AngularClient/src/app/shared/models/portal-resources.ts b/AzureFunctions.AngularClient/src/app/shared/models/portal-resources.ts
index 095ffc2eb6..a528613eb3 100644
--- a/AzureFunctions.AngularClient/src/app/shared/models/portal-resources.ts
+++ b/AzureFunctions.AngularClient/src/app/shared/models/portal-resources.ts
@@ -693,5 +693,9 @@ export class PortalResources
public static rrOverride_message: string = "rrOverride_message";
public static rrOverride_request: string = "rrOverride_request";
public static rrOverride_response: string = "rrOverride_response";
+ public static optional: string = "optional";
+ public static topBar_runtimeV2: string = "topBar_runtimeV2";
+ public static functionKeys_clickToHide: string = "functionKeys_clickToHide";
+ public static expandCollapse: string = "expandCollapse";
}
diff --git a/AzureFunctions.AngularClient/src/app/shared/services/config.service.ts b/AzureFunctions.AngularClient/src/app/shared/services/config.service.ts
index d5a6e09680..3f93b0f390 100644
--- a/AzureFunctions.AngularClient/src/app/shared/services/config.service.ts
+++ b/AzureFunctions.AngularClient/src/app/shared/services/config.service.ts
@@ -1,4 +1,5 @@
-import { Injectable } from '@angular/core';
+import { FunctionsVersionInfo } from '../../../../../common/models/functions-version-info';
+import { Injectable } from '@angular/core';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/toPromise';
@@ -6,6 +7,10 @@ import 'rxjs/add/operator/toPromise';
export class ConfigService {
private runtimeType = window.appsvc.env.runtimeType;
+ get FunctionsVersionInfo(): FunctionsVersionInfo {
+ return window.appsvc.functionsVersionInfo;
+ }
+
isOnPrem(): boolean {
return this.runtimeType === 'OnPrem';
}
diff --git a/AzureFunctions.AngularClient/src/app/shared/services/functions.service.ts b/AzureFunctions.AngularClient/src/app/shared/services/functions.service.ts
index b5a9948554..679b5cd1cd 100644
--- a/AzureFunctions.AngularClient/src/app/shared/services/functions.service.ts
+++ b/AzureFunctions.AngularClient/src/app/shared/services/functions.service.ts
@@ -37,12 +37,6 @@ export class FunctionsService {
private _userService: UserService,
private _globalStateService: GlobalStateService) {
- if (!Constants.runtimeVersion) {
- this.getLatestRuntime().subscribe((runtime: any) => {
- Constants.runtimeVersion = runtime;
- });
- }
-
if (!_globalStateService.showTryView) {
this._userService.getStartupInfo().subscribe(info => { this.token = info.token });
}
@@ -124,14 +118,6 @@ export class FunctionsService {
}
}
- getLatestRuntime() {
- return this._http.get(Constants.serviceHost + 'api/latestruntime', { headers: this.getPortalHeaders() })
- .map(r => {
- return r.json();
- })
- .retryWhen(this.retryAntares);
- }
-
// to talk to Functions Portal
private getPortalHeaders(contentType?: string): Headers {
contentType = contentType || 'application/json';
diff --git a/AzureFunctions.AngularClient/src/app/shared/services/global-state.service.ts b/AzureFunctions.AngularClient/src/app/shared/services/global-state.service.ts
index c37062de84..49aadab325 100644
--- a/AzureFunctions.AngularClient/src/app/shared/services/global-state.service.ts
+++ b/AzureFunctions.AngularClient/src/app/shared/services/global-state.service.ts
@@ -6,7 +6,6 @@ import { ReplaySubject } from 'rxjs/ReplaySubject';
import { TopBarNotification } from './../../top-bar/top-bar-models';
import { FunctionContainer } from '../models/function-container';
import { UserService } from './user.service';
-import { Constants } from '../models/constants';
import { BusyStateComponent } from '../../busy-state/busy-state.component';
import { FunctionsService } from './functions.service';
@@ -49,15 +48,6 @@ export class GlobalStateService {
return '';
}
- // The methods below should not be in the globalstate service
- get RoutingExtensionVersion(): string {
- return this._appSettings[Constants.routingExtensionVersionAppSettingName];
- }
-
- get IsRoutingEnabled() {
- return this.RoutingExtensionVersion && this.RoutingExtensionVersion.toLowerCase() !== Constants.disabled;
- }
-
set GlobalBusyStateComponent(busyStateComponent: BusyStateComponent) {
this._globalBusyStateComponent = busyStateComponent;
setTimeout(() => {
diff --git a/AzureFunctions.AngularClient/src/app/side-nav/side-nav.component.ts b/AzureFunctions.AngularClient/src/app/side-nav/side-nav.component.ts
index 986e654b68..e4c7a63119 100644
--- a/AzureFunctions.AngularClient/src/app/side-nav/side-nav.component.ts
+++ b/AzureFunctions.AngularClient/src/app/side-nav/side-nav.component.ts
@@ -64,7 +64,7 @@ export class SideNavComponent implements AfterViewInit {
private _savedSubsKey = '/subscriptions/selectedIds';
private _subscriptionsStream = new ReplaySubject(1);
- private _searchTermStream = new Subject();
+ private _searchTermStream = new ReplaySubject(1);
private _initialized = false;
diff --git a/AzureFunctions.AngularClient/src/app/site/function-runtime/function-runtime.component.html b/AzureFunctions.AngularClient/src/app/site/function-runtime/function-runtime.component.html
index 78f85c17dd..804d9b6d02 100644
--- a/AzureFunctions.AngularClient/src/app/site/function-runtime/function-runtime.component.html
+++ b/AzureFunctions.AngularClient/src/app/site/function-runtime/function-runtime.component.html
@@ -48,6 +48,9 @@
+
diff --git a/AzureFunctions.AngularClient/src/app/site/function-runtime/function-runtime.component.ts b/AzureFunctions.AngularClient/src/app/site/function-runtime/function-runtime.component.ts
index c46ec8b5de..aa569da819 100644
--- a/AzureFunctions.AngularClient/src/app/site/function-runtime/function-runtime.component.ts
+++ b/AzureFunctions.AngularClient/src/app/site/function-runtime/function-runtime.component.ts
@@ -1,3 +1,4 @@
+import { ConfigService } from './../../shared/services/config.service';
import { SiteTabComponent } from './../site-dashboard/site-tab/site-tab.component';
import { BusyStateComponent } from './../../busy-state/busy-state.component';
import { EditModeHelper } from './../../shared/Utilities/edit-mode.helper';
@@ -32,6 +33,7 @@ import { FunctionApp } from './../../shared/function-app';
import { FunctionAppEditMode } from '../../shared/models/function-app-edit-mode';
import { SlotsService } from '../../shared/services/slots.service';
import { HostStatus } from './../../shared/models/host-status';
+import { FunctionsVersionInfoHelper } from '../../../../../common/models/functions-version-info';
@Component({
selector: 'function-runtime',
@@ -57,6 +59,8 @@ export class FunctionRuntimeComponent implements OnDestroy {
public routingExtensionVersion: string;
public latestRoutingExtensionVersion: string;
public apiProxiesEnabled: boolean;
+ public functionRutimeOptions: SelectOption [];
+ public functionRuntimeValueStream: Subject;
private proxySettingValueStream: Subject;
private functionEditModeValueStream: Subject;
public showTryView: boolean;
@@ -84,6 +88,7 @@ export class FunctionRuntimeComponent implements OnDestroy {
private _aiService: AiService,
private _translateService: TranslateService,
private _slotsService: SlotsService,
+ private _configService: ConfigService,
siteTabsComponent: SiteTabComponent
) {
@@ -143,24 +148,22 @@ export class FunctionRuntimeComponent implements OnDestroy {
this.showDailyMemoryWarning = (!this.site.properties.enabled && this.site.properties.siteDisabledReason === 1);
this.memorySize = this.site.properties.containerSize;
- this.latestExtensionVersion = Constants.runtimeVersion;
this.extensionVersion = appSettings.properties[Constants.runtimeVersionAppSettingName];
if (!this.extensionVersion) {
this.extensionVersion = Constants.latest;
}
- this.needUpdateExtensionVersion =
- Constants.runtimeVersion !== this.extensionVersion && Constants.latest !== this.extensionVersion.toLowerCase();
+ this.setNeedUpdateExtensionVersion();
this.routingExtensionVersion = appSettings.properties[Constants.routingExtensionVersionAppSettingName];
if (!this.routingExtensionVersion) {
this.routingExtensionVersion = Constants.disabled;
}
- this.latestRoutingExtensionVersion = Constants.routingExtensionVersion;
+ this.latestRoutingExtensionVersion = this._configService.FunctionsVersionInfo.proxyDefault;
this.apiProxiesEnabled = ((this.routingExtensionVersion) && (this.routingExtensionVersion !== Constants.disabled));
this.needUpdateRoutingExtensionVersion
- = Constants.routingExtensionVersion !== this.routingExtensionVersion && Constants.latest !== this.routingExtensionVersion.toLowerCase();
+ = this._configService.FunctionsVersionInfo.proxyDefault !== this.routingExtensionVersion && Constants.latest !== this.routingExtensionVersion.toLowerCase();
if (EditModeHelper.isReadOnly(r.editMode)) {
this.functionAppEditMode = false;
@@ -206,27 +209,36 @@ export class FunctionRuntimeComponent implements OnDestroy {
value: true
}];
- this.proxySettingValueStream = new Subject();
- this.proxySettingValueStream
- .subscribe((value: boolean) => {
- if (this.apiProxiesEnabled !== value) {
- this._busyState.setBusyState();
- const appSettingValue: string = value ? Constants.routingExtensionVersion : Constants.disabled;
+ this.functionRutimeOptions = [
+ {
+ displayLabel: '~1',
+ value: '~1'
+ }, {
+ displayLabel: '~2 (beta)',
+ value: '~2'
+ }];
- this._cacheService.postArm(`${this.site.id}/config/appsettings/list`, true)
- .mergeMap(r => {
- return this._updateProxiesVersion(r.json(), appSettingValue);
- })
- .subscribe(() => {
- this.functionApp.fireSyncTrigger();
- this.apiProxiesEnabled = value;
- this.needUpdateRoutingExtensionVersion = false;
- this.routingExtensionVersion = Constants.routingExtensionVersion;
- this._busyState.clearBusyState();
- this._cacheService.clearArmIdCachePrefix(this.site.id);
- });
- }
- });
+ this.proxySettingValueStream = new Subject();
+ this.proxySettingValueStream
+ .subscribe((value: boolean) => {
+ if (this.apiProxiesEnabled !== value) {
+ this._busyState.setBusyState();
+ const appSettingValue: string = value ? this._configService.FunctionsVersionInfo.proxyDefault : Constants.disabled;
+
+ this._cacheService.postArm(`${this.site.id}/config/appsettings/list`, true)
+ .mergeMap(r => {
+ return this._updateProxiesVersion(r.json(), appSettingValue);
+ })
+ .subscribe(() => {
+ this.functionApp.fireSyncTrigger();
+ this.apiProxiesEnabled = value;
+ this.needUpdateRoutingExtensionVersion = false;
+ this.routingExtensionVersion = this._configService.FunctionsVersionInfo.proxyDefault;
+ this._busyState.clearBusyState();
+ this._cacheService.clearArmIdCachePrefix(this.site.id);
+ });
+ }
+ });
this.functionEditModeValueStream = new Subject();
this.functionEditModeValueStream
@@ -285,6 +297,11 @@ export class FunctionRuntimeComponent implements OnDestroy {
this._cacheService.clearArmIdCachePrefix(this.site.id);
});
});
+
+ this.functionRuntimeValueStream = new Subject();
+ this.functionRuntimeValueStream.subscribe((value: string) => {
+ this.updateVersion(value);
+ });
}
@Input('viewInfoInput') set viewInfoInput(viewInfo: TreeViewInfo) {
@@ -316,15 +333,26 @@ export class FunctionRuntimeComponent implements OnDestroy {
return navigator.userAgent.toLocaleLowerCase().indexOf('trident') !== -1;
}
- updateVersion() {
+ updateVersion(version?: string) {
+ if (version === this.extensionVersion) {
+ return;
+ }
+ if (!version) {
+ version = this.getLatestVersion(this.extensionVersion);
+ };
this._aiService.trackEvent('/actions/app_settings/update_version');
this._busyState.setBusyState();
this._cacheService.postArm(`${this.site.id}/config/appsettings/list`, true)
.mergeMap(r => {
- return this._updateContainerVersion(r.json());
+ return this._updateContainerVersion(r.json(), version);
})
- .subscribe(() => {
- this.needUpdateExtensionVersion = false;
+ .mergeMap(r => {
+ return this.functionApp.getFunctionHostStatus();
+ })
+ .subscribe((hostStatus: HostStatus) => {
+ this.exactExtensionVersion = hostStatus ? hostStatus.version : '';
+ this.extensionVersion = version;
+ this.setNeedUpdateExtensionVersion();
this._busyState.clearBusyState();
this._cacheService.clearArmIdCachePrefix(this.site.id);
this._appNode.clearNotification(NotificationIds.newRuntimeVersion);
@@ -337,7 +365,7 @@ export class FunctionRuntimeComponent implements OnDestroy {
this._cacheService.postArm(`${this.site.id}/config/appsettings/list`, true)
.mergeMap(r => {
- return this._updateProxiesVersion(r.json(), Constants.routingExtensionVersion);
+ return this._updateProxiesVersion(r.json(), this._configService.FunctionsVersionInfo.proxyDefault);
})
.subscribe(() => {
this.needUpdateRoutingExtensionVersion = false;
@@ -381,11 +409,11 @@ export class FunctionRuntimeComponent implements OnDestroy {
this._broadcastService.broadcast(BroadcastEvent.OpenTab, SiteTabIds.applicationSettings);
}
- private _updateContainerVersion(appSettings: ArmObj) {
+ private _updateContainerVersion(appSettings: ArmObj, version: string) {
if (appSettings.properties[Constants.azureJobsExtensionVersion]) {
delete appSettings[Constants.azureJobsExtensionVersion];
}
- appSettings.properties[Constants.runtimeVersionAppSettingName] = Constants.runtimeVersion;
+ appSettings.properties[Constants.runtimeVersionAppSettingName] = version;
appSettings.properties[Constants.nodeVersionAppSettingName] = Constants.nodeVersion;
return this._cacheService.putArm(appSettings.id, this._armService.websiteApiVersion, appSettings);
@@ -400,7 +428,7 @@ export class FunctionRuntimeComponent implements OnDestroy {
if (appSettings[Constants.routingExtensionVersionAppSettingName]) {
delete appSettings.properties[Constants.routingExtensionVersionAppSettingName];
}
- appSettings.properties[Constants.routingExtensionVersionAppSettingName] = value ? value : Constants.routingExtensionVersion;
+ appSettings.properties[Constants.routingExtensionVersionAppSettingName] = value ? value : this._configService.FunctionsVersionInfo.proxyDefault;
return this._cacheService.putArm(appSettings.id, this._armService.websiteApiVersion, appSettings);
}
@@ -430,4 +458,26 @@ export class FunctionRuntimeComponent implements OnDestroy {
public get GlobalDisabled() {
return this._globalStateService.GlobalDisabled;
}
+
+ private setNeedUpdateExtensionVersion() {
+ this.needUpdateExtensionVersion = FunctionsVersionInfoHelper.needToUpdateRuntime(this._configService.FunctionsVersionInfo, this.extensionVersion);
+ this.latestExtensionVersion = this.getLatestVersion(this.extensionVersion);
+ }
+
+ private getLatestVersion(version: string): string {
+ const match = this._configService.FunctionsVersionInfo.runtimeStable.find(v => {
+ return this.extensionVersion.toLowerCase() === v;
+ });
+ if (match) {
+ return match;
+ } else {
+ if (version.startsWith('1.')) {
+ return '~1';
+ } else if (version.startsWith('2.')) {
+ return '~2';
+ } else {
+ return this._configService.FunctionsVersionInfo.runtimeDefault;
+ }
+ }
+ }
}
diff --git a/AzureFunctions.AngularClient/src/app/site/site-dashboard/site-dashboard.component.html b/AzureFunctions.AngularClient/src/app/site/site-dashboard/site-dashboard.component.html
index d5b851911d..0499e3bc70 100644
--- a/AzureFunctions.AngularClient/src/app/site/site-dashboard/site-dashboard.component.html
+++ b/AzureFunctions.AngularClient/src/app/site/site-dashboard/site-dashboard.component.html
@@ -7,12 +7,17 @@
src="images/pin.svg"
(click)="pinPart()" />
- |