Skip to content

Commit

Permalink
Merge branch 'master' into k8s_anns_labels_secrets
Browse files Browse the repository at this point in the history
  • Loading branch information
mdirkse authored Oct 16, 2017
2 parents 2e8cb93 + 963e3f0 commit 1ac60fa
Show file tree
Hide file tree
Showing 119 changed files with 2,084 additions and 1,686 deletions.
2 changes: 1 addition & 1 deletion app/scripts/modules/amazon/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@spinnaker/amazon",
"version": "0.0.39",
"version": "0.0.41",
"main": "lib/lib.js",
"typings": "lib/index.d.ts",
"scripts": {
Expand Down
2 changes: 2 additions & 0 deletions app/scripts/modules/amazon/src/help/amazon.help.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const helpContents: {[key: string]: string} = {
<p>However, if your stack name needs to be longer (load balancer names are limited to 32 characters), consider changing it to "elb", or omit it altogether.</p>`,
'aws.loadBalancer.internal': 'Controls the load balancer scheme, <strong>not</strong> the subnet. By default, load balancers are created with a DNS name that resolves to public IP addresses. Specify internal to create a load balancer with a DNS name that resolves to private IP addresses.',
'aws.loadBalancer.stack': '(Optional) <b>Stack</b> is one of the core naming components of a cluster, used to create vertical stacks of dependent services for integration testing.',
'aws.loadBalancer.name': '<p>The load balancer name is formed by combining the application name, the <b>Stack</b> field, and the <b>Detail</b> field.</p>',
'aws.loadBalancer.targetGroups': 'Add a target group if you want to associate this with an Application Load Balancer (ALB)',
'aws.loadBalancer.loadBalancers': 'And a load balancer directly if you created a Classic Load Balancer (a classic load balancer does not have target groups)',
'aws.loadBalancer.ruleCondition.host':
Expand Down Expand Up @@ -78,6 +79,7 @@ const helpContents: {[key: string]: string} = {
<p>The VPC to which this security group will apply.</p>
<p>If you wish to use VPC but are unsure which VPC to use, the most common one is "Main".</p>
<p>If you do not wish to use VPC, select "None".</p>`,
'aws.securityGroup.name': '<p>The security group name is formed by combining the application name, the <b>Stack</b> field, and the <b>Detail</b> field.</p>',
'aws.scalingPolicy.search.restricted':
`<p>Resets dimensions to "AutoScalingGroupName: {name of the ASG}" and provides
a simpler, combined input for the namespace and metric name fields.</p>`,
Expand Down
1 change: 1 addition & 0 deletions app/scripts/modules/amazon/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export { AMAZON_MODULE } from './aws.module';
export * from './aws.settings';

export * from './domain';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<div class="col-md-12 well" ng-class="{'alert-danger': form.loadBalancerName.$error.validateUnique && ctrl.enforceUniqueName, 'alert-info': !form.loadBalancerName.$error.validateUnique}">
<strong>Your load balancer will be named:</strong>
<span>{{ctrl.getName()}}</span>
<help-field key="aws.loadBalancer.name"></help-field>
<!-- Angular does not seem to run length validation on hidden inputs, hence the text + display:none -->
<input type="text"
style="display: none"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ module.exports = angular
v2modalWizardService,
cacheInitializer,
infrastructureCaches,
namingService,
vpcReader) {


Expand Down Expand Up @@ -304,11 +305,8 @@ module.exports = angular
};

ctrl.updateName = function () {
var securityGroup = $scope.securityGroup,
name = application.name;
if (securityGroup.detail) {
name += '-' + securityGroup.detail;
}
const { securityGroup } = $scope;
const name = namingService.getClusterName(application.name, securityGroup.stack, securityGroup.detail);
securityGroup.name = name;
$scope.namePreview = name;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<div class="col-md-12 well" ng-class="{'alert-danger': form.securityGroupName.$error.validateUnique, 'alert-info': !form.securityGroupName.$error.validateUnique}">
<strong>Your security group will be named:</strong>
<span ng-bind="namePreview"></span>
<help-field key="aws.securityGroup.name"></help-field>
<input type="hidden" class="form-control input-sm"
ng-model="securityGroup.name"
validate-unique="existingSecurityGroupNames"
Expand All @@ -17,35 +18,45 @@
</div>
</div>
<div class="form-group">
<div class="col-md-4 sm-label-right">Detail (optional)</div>
<div class="col-md-4">
<input type="text" class="form-control input-sm no-spel"
ng-model="securityGroup.detail"
ng-change="ctrl.updateName()"/>
<div class="col-md-3 sm-label-right">Account</div>
<div class="col-md-8">
<account-select-field component="securityGroup" field="credentials" accounts="accounts" provider="'aws'" on-change="ctrl.accountUpdated()"></account-select-field>
</div>
</div>
<div class="form-group">
<div class="col-md-4 sm-label-right">Description</div>
<div class="col-md-3 sm-label-right">Regions</div>
<div class="col-md-8">
<input type="text" required class="form-control input-sm no-spel" ng-model="securityGroup.description" />
<input type="hidden" ng-model="securityGroup.regions[0]" required/>
<checklist ng-if="securityGroup.credentials" items="regions" model="securityGroup.regions" inline="true" on-change="ctrl.regionUpdated()"></checklist>
<p class="form-control-static" ng-if="!securityGroup.credentials">(Select an account)</p>
</div>
</div>
<div class="form-group">
<div class="col-md-4 sm-label-right">Account</div>
<div class="col-md-8">
<account-select-field component="securityGroup" field="credentials" accounts="accounts" provider="'aws'" on-change="ctrl.accountUpdated()"></account-select-field>
<div class="col-md-3 sm-label-right">Stack</div>
<div class="col-md-3">
<input type="text" class="form-control input-sm no-spel"
ng-model="securityGroup.stack"
ng-change="ctrl.updateName()"/>
</div>
<div class="col-md-2 sm-label-right">Detail</div>
<div class="col-md-3">
<input type="text" class="form-control input-sm no-spel"
ng-model="securityGroup.detail"
ng-change="ctrl.updateName()"/>
</div>
</div>
<div class="form-group">
<div class="col-md-4 sm-label-right">Regions</div>
<div class="col-md-3 sm-label-right">Description (required)</div>
<div class="col-md-8">
<input type="hidden" ng-model="securityGroup.regions[0]" required/>
<checklist ng-if="securityGroup.credentials" items="regions" model="securityGroup.regions" inline="true" on-change="ctrl.regionUpdated()"></checklist>
<p class="form-control-static" ng-if="!securityGroup.credentials">(Select an account)</p>
<textarea required
cols=2
class="form-control input-sm no-spel"
ng-model="securityGroup.description">
</textarea>
</div>
</div>
<div class="form-group">
<div class="col-md-4 sm-label-right">VPC <help-field key="aws.securityGroup.vpc"></help-field></div>
<div class="col-md-3 sm-label-right">VPC <help-field key="aws.securityGroup.vpc"></help-field></div>
<div class="col-md-8">
<select class="form-control input-sm" ng-model="securityGroup.vpcId"
ng-change="ctrl.vpcUpdated()"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ module.exports = angular.module('spinnaker.amazon.serverGroupCommandBuilder.serv
var useAmiBlockDeviceMappings = applicationAwsSettings.useAmiBlockDeviceMappings || false;

var command = {
application: application.name,
application: application,
credentials: defaultCredentials,
region: defaultRegion,
strategy: '',
Expand Down Expand Up @@ -189,7 +189,7 @@ module.exports = angular.module('spinnaker.amazon.serverGroupCommandBuilder.serv
var useAmiBlockDeviceMappings = applicationAwsSettings.useAmiBlockDeviceMappings || false;

var command = {
application: application.name,
application: application,
strategy: '',
stack: serverGroupName.stack,
freeFormDetails: serverGroupName.freeFormDetails,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { module, IPromise, IQService } from 'angular';
import { chain, clone, cloneDeep, extend, find, flatten, has, intersection, keys, map, some, xor } from 'lodash';
import { chain, clone, cloneDeep, extend, find, flatten, has, intersection, isNil, keys, map, some, xor } from 'lodash';

import {
ACCOUNT_SERVICE,
Expand Down Expand Up @@ -29,6 +29,8 @@ import {

import { IAmazonLoadBalancer, IKeyPair } from 'amazon/domain';
import { KEY_PAIRS_READ_SERVICE, KeyPairsReader } from 'amazon/keyPairs/keyPairs.read.service';
import { IMoniker } from 'core/naming/IMoniker';
import { NamingService } from 'core/naming/naming.service';

export type IBlockDeviceMappingSource = 'source' | 'ami' | 'default';

Expand Down Expand Up @@ -66,6 +68,7 @@ export interface IAmazonServerGroupCommand extends IServerGroupCommand {
getBlockDeviceMappingsSource: () => IBlockDeviceMappingSource;
selectBlockDeviceMappingsSource: (selection: string) => void;
usePreferredZonesChanged: () => IAmazonServerGroupCommandResult;
clusterChanged: () => void;
}

export class AwsServerGroupConfigurationService {
Expand All @@ -82,6 +85,7 @@ export class AwsServerGroupConfigurationService {
private subnetReader: SubnetReader,
private keyPairsReader: KeyPairsReader,
private loadBalancerReader: LoadBalancerReader,
private namingService: NamingService,
private serverGroupCommandRegistry: ServerGroupCommandRegistry,
private autoScalingProcessService: any) {
'ngInject';
Expand Down Expand Up @@ -567,6 +571,17 @@ export class AwsServerGroupConfigurationService {
return result;
};

command.clusterChanged = (): void => {
const appName = isNil(command.application) ? undefined : command.application.name;
const moniker: IMoniker = {
app: appName,
stack: command.stack,
detail: command.freeFormDetails,
cluster: this.namingService.getClusterName(appName, command.stack, command.freeFormDetails)
};
command.moniker = moniker;
};

command.credentialsChanged = (): IServerGroupCommandResult => {
const result: IAmazonServerGroupCommandResult = { dirty: {} };
const backingData = command.backingData;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export class CreateScalingPolicyButton extends React.Component<ICreateScalingPol
serverGroup: () => serverGroup,
application: () => application,
}
});
}).result.catch(() => {});
}

public createTargetTrackingPolicy(): void {
Expand All @@ -64,7 +64,7 @@ export class CreateScalingPolicyButton extends React.Component<ICreateScalingPol
serverGroup: () => serverGroup,
application: () => application,
}
});
}).result.catch(() => {});
}

public typeSelected(typeSelection: string): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export class AwsServerGroupTransformer {
policyOrStepAdjustment.absAdjustment = Math.abs(policyOrStepAdjustment.scalingAdjustment);
}

private transformScalingPolicy(policy: IScalingPolicy): IScalingPolicyView {
public transformScalingPolicy(policy: IScalingPolicy): IScalingPolicyView {
const view: IScalingPolicyView = Object.assign({}, policy) as IScalingPolicyView;
const upperBoundSorter = (a: IStepAdjustmentView, b: IStepAdjustmentView) => b.metricIntervalUpperBound - a.metricIntervalUpperBound,
lowerBoundSorter = (a: IStepAdjustmentView, b: IStepAdjustmentView) => a.metricIntervalLowerBound - b.metricIntervalLowerBound;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { IPromise, IQService, module } from 'angular';
import { intersection } from 'lodash';

import {
ACCOUNT_SERVICE,
Expand Down Expand Up @@ -79,13 +78,13 @@ export class AppengineServerGroupCommandBuilder {
const viewState: IViewState = {
mode: mode,
submitButtonLabel: this.getSubmitButtonLabel(mode),
disableStrategySelection: mode === 'create' ? true : false,
disableStrategySelection: mode === 'create',
};

return this.$q.all(dataToFetch)
.then((backingData: any) => {
const credentials: string = this.getCredentials(backingData.accounts, app);
const region: string = this.getRegion(backingData.accounts, credentials);
const credentials = this.getCredentials(backingData.accounts);
const region = this.getRegion(backingData.accounts, credentials);

return {
application: app.name,
Expand Down Expand Up @@ -126,14 +125,13 @@ export class AppengineServerGroupCommandBuilder {
});
}

private getCredentials(accounts: IAppengineAccount[], application: Application): string {
private getCredentials(accounts: IAppengineAccount[]): string {
const accountNames: string[] = (accounts || []).map((account) => account.name);
const defaultCredentials: string = AppengineProviderSettings.defaults.account;
const firstApplicationAccount: string = intersection(application.accounts || [], accountNames)[0];

return accountNames.includes(defaultCredentials) ?
defaultCredentials :
(firstApplicationAccount || 'my-appengine-account');
return accountNames.includes(defaultCredentials)
? defaultCredentials
: accountNames[0];
}

private getRegion(accounts: IAppengineAccount[], credentials: string): string {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@ class AppengineServerGroupBasicSettingsCtrl implements IController {
const account = this.findAccountInBackingData();
if (account) {
this.$scope.command.gitCredentialType = account.supportedGitCredentialTypes[0];
this.$scope.command.region = account.region;
} else {
this.$scope.command.gitCredentialType = 'NONE';
delete this.$scope.command.region;
}
}

Expand Down
2 changes: 1 addition & 1 deletion app/scripts/modules/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@spinnaker/core",
"version": "0.0.78",
"version": "0.0.85",
"main": "lib/lib.js",
"typings": "lib/index.d.ts",
"scripts": {
Expand Down
78 changes: 78 additions & 0 deletions app/scripts/modules/core/src/api/network.interceptor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import {
IDeferred, IHttpInterceptor, IHttpPromiseCallbackArg, IHttpProvider, IPromise, IQService, IRequestConfig,
ITimeoutService, IWindowService, module
} from 'angular';
import { Dictionary } from 'lodash';
import { BindAll } from 'lodash-decorators';

/**
* Handles two scenarios:
* 1. computer loses network connection (retries connections when network returns)
* 2. requests are aborted due to a network change (retries immediately)
*/

@BindAll()
export class NetworkInterceptor implements IHttpInterceptor {

private networkAvailable: IDeferred<void>;
private retryQueue: Dictionary<number> = {};
private MAX_RETRIES = 4;

constructor(private $q: IQService,
private $window: IWindowService,
private $timeout: ITimeoutService,
private $injector: any) {
'ngInject';
this.$window.addEventListener('offline', this.handleOffline);
this.$window.addEventListener('online', this.handleOnline);
this.resetNetworkAvailable();
}

private handleOffline(): void {
this.networkAvailable = this.$q.defer();
}

private handleOnline(): void {
this.networkAvailable.resolve();
this.resetNetworkAvailable();
}

private resetNetworkAvailable(): void {
this.networkAvailable = this.$q.defer();
this.networkAvailable.resolve();
}

private removeFromQueue(config: IRequestConfig): void {
delete this.retryQueue[config.url];
}

// see http://www.couchcoder.com/angular-1-interceptors-using-typescript for more details on why we need to do this
// in essence, we need to do this because "the ng1 implementation of interceptors only keeps references to the handler
// functions themselves and invokes them directly without any context (stateless) which means we lose `this` inside
// the handlers"
public responseError = <T>(response: IHttpPromiseCallbackArg<T>): IPromise<T> => {
const { config, status } = response;
// status of -1 indicates the request was aborted, retry if we haven't already, with incremental backoff + jitter
const retryCount = this.retryQueue[config.url] || 0;
if (status === -1 && retryCount < this.MAX_RETRIES) {
this.retryQueue[config.url] = retryCount + 1;
return this.networkAvailable.promise.then(() => {
return this.$timeout(() => {
return this.$q.resolve(this.$injector.get('$http')(config))
.then((result: any) => {
this.removeFromQueue(config);
return result;
});
}, (retryCount + 1 + Math.random()) * 1000);
});
}
return this.$q.reject(response).finally(() => this.removeFromQueue(config));
}
}

export const NETWORK_INTERCEPTOR = 'spinnaker.core.network.interceptor';
module(NETWORK_INTERCEPTOR, [])
.service('networkInterceptor', NetworkInterceptor)
.config(($httpProvider: IHttpProvider) => {
$httpProvider.interceptors.push('networkInterceptor');
});
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export class ApplicationComponent extends React.Component<IApplicationComponentP
resolve: {
application: () => this.props.app
}
})
}).result.catch(() => {});
}

public handleRefresh(): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,6 @@ module(APPLICATION_MODULE, [
UPSERT_APPLICATION_HELP,
])
.run(($state: StateService, applicationReader: ApplicationReader) => {
'ngInject';
PostSearchResultSearcherRegistry.register('applications', 'serverGroups', new ApplicationPostSearchResultSearcher($state, applicationReader));
});
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,7 @@ export class ApplicationDataSource implements IDataSourceConfig {
this.refreshStream.take(1).subscribe(deferred.resolve);
this.refreshFailureStream.take(1).subscribe(deferred.reject);
}
deferred.promise.catch(() => {});
return deferred.promise;
}

Expand Down
Loading

0 comments on commit 1ac60fa

Please sign in to comment.