Skip to content

Commit

Permalink
feat(entityTags):kubernetes support (#5498)
Browse files Browse the repository at this point in the history
  • Loading branch information
nvndnl authored and lwander committed Nov 19, 2018
1 parent 0525282 commit 7a4b0cd
Show file tree
Hide file tree
Showing 22 changed files with 331 additions and 28 deletions.
33 changes: 20 additions & 13 deletions app/scripts/modules/core/src/application/nav/CategoryDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,24 @@ export class CategoryDropdown extends React.Component<ICategoryDropdownProps, IC
runningCount: withBadges.reduce((acc: number, ds: ApplicationDataSource) => acc + ds.data.length, 0),
});
});
this.entityTagsSubscription = merge(...category.dataSources.map(ds => ds.refresh$)).subscribe(() => {
const tags = category.dataSources.reduce(
(acc: IEntityTags[], ds: ApplicationDataSource) => acc.concat(ds.alerts || []),
[],
);
this.setState({ tags });
});
if (category.key === 'delivery') {
const withTags = [application.getDataSource('executions'), application.getDataSource('pipelineConfigs')];
this.entityTagsSubscription = merge(...withTags.map(ds => ds.refresh$)).subscribe(() => {
const tags = withTags.reduce(
(acc: IEntityTags[], ds: ApplicationDataSource) => acc.concat(ds.alerts || []),
[],
);
this.setState({ tags });
});
} else {
this.entityTagsSubscription = merge(...category.dataSources.map(ds => ds.refresh$)).subscribe(() => {
const tags = category.dataSources.reduce(
(acc: IEntityTags[], ds: ApplicationDataSource) => acc.concat(ds.alerts || []),
[],
);
this.setState({ tags });
});
}
}

private clearSubscriptions(): void {
Expand All @@ -89,7 +100,7 @@ export class CategoryDropdown extends React.Component<ICategoryDropdownProps, IC
};

private createNonMenuEntry(): JSX.Element {
const { runningCount } = this.state;
const { runningCount, tags } = this.state;
const { category, application } = this.props;
const dataSource = category.dataSources[0];
return (
Expand All @@ -99,11 +110,7 @@ export class CategoryDropdown extends React.Component<ICategoryDropdownProps, IC
<NavIcon icon={dataSource.icon} />
{' ' + dataSource.label}
{runningCount > 0 && <span className="badge badge-running-count">{runningCount}</span>}
<DataSourceNotifications
tags={dataSource.alerts || []}
application={application}
tabName={category.label}
/>
<DataSourceNotifications tags={tags} application={application} tabName={category.label} />
</a>
</UISref>
</UISrefActive>
Expand Down
2 changes: 2 additions & 0 deletions app/scripts/modules/core/src/domain/IExecution.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { IEntityTags } from './IEntityTags';
import { IOrchestratedItem } from './IOrchestratedItem';
import { IExecutionTrigger } from './IExecutionTrigger';
import { IExecutionStage, IExecutionStageSummary } from './IExecutionStage';
Expand All @@ -13,6 +14,7 @@ export interface IExecution extends IOrchestratedItem {
currentStages?: IExecutionStageSummary[];
deploymentTargets: string[];
// expandedGroups?: {[groupId: string]: boolean};
entityTags?: IEntityTags;
graphStatusHash?: string;
id: string;
isComplete?: boolean;
Expand Down
2 changes: 2 additions & 0 deletions app/scripts/modules/core/src/domain/IPipeline.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { IStage } from './IStage';
import { ITrigger } from './ITrigger';
import { IExpectedArtifact } from 'core/domain/IExpectedArtifact';
import { IEntityTags } from './IEntityTags';

export interface IPipeline {
application: string;
description?: string;
entityTags?: IEntityTags;
id: string;
index: number;
isNew?: boolean;
Expand Down
3 changes: 3 additions & 0 deletions app/scripts/modules/core/src/domain/IServerGroupManager.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { IMoniker } from 'core/naming';
import { IEntityTags } from 'core/domain';

export interface IServerGroupManager {
account: string;
cloudProvider: string;
displayName?: string;
entityTags?: IEntityTags;
moniker: IMoniker;
name: string;
region: string;
Expand Down
3 changes: 3 additions & 0 deletions app/scripts/modules/core/src/entityTag/EntityTagEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ export class EntityTagEditor extends React.Component<IEntityTagEditorProps, IEnt
const entityType: string = values.ownerOption ? values.ownerOption.type : this.props.entityType;

const entityRef: IEntityRef = this.props.entityRef || EntityRefBuilder.getBuilder(entityType)(owner);
if (!entityRef.application) {
entityRef.application = application.name;
}

tag.value.message = values.message;

Expand Down
44 changes: 41 additions & 3 deletions app/scripts/modules/core/src/entityTag/EntityTagsReader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { $q } from 'ngimport';
import { API } from 'core/api/ApiService';
import { IEntityTags, IEntityTag, ICreationMetadataTag } from '../domain/IEntityTags';
import { Application } from 'core/application/application.model';
import { IServerGroup, ILoadBalancer, ISecurityGroup } from 'core/domain';
import { IExecution, IPipeline, IServerGroup, IServerGroupManager, ILoadBalancer, ISecurityGroup } from 'core/domain';
import { SETTINGS } from 'core/config/settings';

export class EntityTagsReader {
Expand Down Expand Up @@ -39,14 +39,30 @@ export class EntityTagsReader {
});
}

public static addTagsToServerGroupManagers(application: Application): void {
if (!SETTINGS.feature.entityTags) {
return;
}
const allTags = application.getDataSource('entityTags').data;
const serverGroupManagerTags: IEntityTags[] = allTags.filter(t => t.entityRef.entityType === 'servergroupmanager');
application.getDataSource('serverGroupManagers').data.forEach((serverGroupManager: IServerGroupManager) => {
serverGroupManager.entityTags = serverGroupManagerTags.find(
t =>
t.entityRef.entityId === serverGroupManager.name &&
t.entityRef.account === serverGroupManager.account &&
t.entityRef.region === serverGroupManager.region,
);
});
}

public static addTagsToLoadBalancers(application: Application): void {
if (!SETTINGS.feature.entityTags) {
return;
}
const allTags = application.getDataSource('entityTags').data;
const serverGroupTags: IEntityTags[] = allTags.filter(t => t.entityRef.entityType === 'loadbalancer');
const loadBalancerTags: IEntityTags[] = allTags.filter(t => t.entityRef.entityType === 'loadbalancer');
application.getDataSource('loadBalancers').data.forEach((loadBalancer: ILoadBalancer) => {
loadBalancer.entityTags = serverGroupTags.find(
loadBalancer.entityTags = loadBalancerTags.find(
t =>
t.entityRef.entityId === loadBalancer.name &&
t.entityRef.account === loadBalancer.account &&
Expand All @@ -71,6 +87,28 @@ export class EntityTagsReader {
});
}

public static addTagsToExecutions(application: Application): void {
if (!SETTINGS.feature.entityTags) {
return;
}
const allTags = application.getDataSource('entityTags').data;
const executionTags: IEntityTags[] = allTags.filter(t => t.entityRef.entityType === 'execution');
application.getDataSource('executions').data.forEach((execution: IExecution) => {
execution.entityTags = executionTags.find(t => t.entityRef.entityId === execution.id);
});
}

public static addTagsToPipelines(application: Application): void {
if (!SETTINGS.feature.entityTags) {
return;
}
const allTags = application.getDataSource('entityTags').data;
const pipelineTags: IEntityTags[] = allTags.filter(t => t.entityRef.entityType === 'pipeline');
application.getDataSource('pipelineConfigs').data.forEach((pipeline: IPipeline) => {
pipeline.entityTags = pipelineTags.find(t => t.entityRef.entityId === pipeline.name);
});
}

public static getEntityTagsForId(entityType: string, entityId: string): IPromise<IEntityTags[]> {
if (!entityId) {
return $q.when([]);
Expand Down
52 changes: 46 additions & 6 deletions app/scripts/modules/core/src/entityTag/clusterTargetBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { IServerGroup } from 'core/domain';
import { NameUtils } from 'core/naming';
import { IServerGroup, IServerGroupManager } from 'core/domain';
// import { NameUtils } from 'core/naming';

import { IOwnerOption } from './EntityTagEditor';

export class ClusterTargetBuilder {
public static buildClusterTargets(serverGroup: IServerGroup): IOwnerOption[] {
const clusterName = NameUtils.getClusterNameFromServerGroupName(serverGroup.name);
const clusterName = serverGroup.moniker.cluster;
const regionName = serverGroup.cloudProvider === 'kubernetes' ? 'namespace' : 'region';
return [
{
type: 'serverGroup',
Expand All @@ -18,23 +19,62 @@ export class ClusterTargetBuilder {
label: `all server groups in **${serverGroup.region}** in ${clusterName}`,
owner: {
name: clusterName,
cloudProvider: 'aws',
cloudProvider: serverGroup.cloudProvider,
region: serverGroup.region,
account: serverGroup.account,
},
isDefault: false,
},
{
type: 'cluster',
label: `all server groups in **all regions** in ${clusterName}`,
label: `all server groups in **all ${regionName}s** in ${clusterName}`,
owner: {
name: clusterName,
cloudProvider: 'aws',
cloudProvider: serverGroup.cloudProvider,
region: '*',
account: serverGroup.account,
},
isDefault: false,
},
];
}

public static buildManagerClusterTargets(serverGroupManager: IServerGroupManager): IOwnerOption[] {
const clusterName = serverGroupManager.moniker.cluster;
return [
{
type: 'serverGroupManager',
label: `all server groups in **${serverGroupManager.displayName}** in ${clusterName}`,
owner: {
name: serverGroupManager.name,
cloudProvider: serverGroupManager.cloudProvider,
region: serverGroupManager.region,
account: serverGroupManager.account,
},
isDefault: true,
},
{
type: 'cluster',
label: `all server groups in **${serverGroupManager.region}** in ${clusterName}`,
owner: {
name: clusterName,
cloudProvider: serverGroupManager.cloudProvider,
region: serverGroupManager.region,
account: serverGroupManager.account,
},
isDefault: true,
},
{
type: 'cluster',
label: `all server groups in **all namespaces** in ${clusterName}`,
owner: {
name: clusterName,
cloudProvider: serverGroupManager.cloudProvider,
region: '*',
account: serverGroupManager.account,
},
isDefault: false,
},
];
}
}
21 changes: 20 additions & 1 deletion app/scripts/modules/core/src/entityTag/entityRef.builder.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import { Application } from 'core/application/application.model';
import { IEntityRef, ILoadBalancer, IRegionalCluster, ISecurityGroup, IServerGroup } from 'core/domain';
import {
IEntityRef,
ILoadBalancer,
IRegionalCluster,
ISecurityGroup,
IServerGroup,
IServerGroupManager,
} from 'core/domain';

export class EntityRefBuilder {
public static buildServerGroupRef(serverGroup: IServerGroup): IEntityRef {
Expand All @@ -12,6 +19,16 @@ export class EntityRefBuilder {
};
}

public static buildServerGroupManagerRef(serverGroupManager: IServerGroupManager): IEntityRef {
return {
cloudProvider: serverGroupManager.cloudProvider,
entityType: 'servergroupmanager',
entityId: serverGroupManager.name,
account: serverGroupManager.account,
region: serverGroupManager.region,
};
}

public static buildLoadBalancerRef(loadBalancer: ILoadBalancer): IEntityRef {
return {
cloudProvider: loadBalancer.cloudProvider,
Expand Down Expand Up @@ -57,6 +74,8 @@ export class EntityRefBuilder {
return this.buildApplicationRef;
case 'serverGroup':
return this.buildServerGroupRef;
case 'serverGroupManager':
return this.buildServerGroupManagerRef;
case 'loadBalancer':
return this.buildLoadBalancerRef;
case 'cluster':
Expand Down
12 changes: 12 additions & 0 deletions app/scripts/modules/core/src/entityTag/entityTags.dataSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ module(ENTITY_TAGS_DATA_SOURCE, [LOAD_BALANCER_READ_SERVICE]).run(($q: IQService
.getDataSource('serverGroups')
.ready()
.then(() => EntityTagsReader.addTagsToServerGroups(application), noop);
application
.getDataSource('serverGroupManagers')
.ready()
.then(() => EntityTagsReader.addTagsToServerGroupManagers(application), noop);
application
.getDataSource('loadBalancers')
.ready()
Expand All @@ -34,6 +38,14 @@ module(ENTITY_TAGS_DATA_SOURCE, [LOAD_BALANCER_READ_SERVICE]).run(($q: IQService
.getDataSource('securityGroups')
.ready()
.then(() => EntityTagsReader.addTagsToSecurityGroups(application), noop);
application
.getDataSource('executions')
.ready()
.then(() => EntityTagsReader.addTagsToExecutions(application), noop);
application
.getDataSource('pipelineConfigs')
.ready()
.then(() => EntityTagsReader.addTagsToPipelines(application), noop);
};

ApplicationDataSourceRegistry.registerDataSource({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ class AlertsForMessage extends React.Component<IAlertsForMessageProps, IAlertsFo
<strong>
<span>
{' '}
{this.state.collapsed ? 'Show' : 'Hide'} {notifications.length} server groups
{this.state.collapsed ? 'Show' : 'Hide'} {notifications.length} entities
</span>
</strong>
</a>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,14 @@ export interface INotificationListProps {
export class NotificationList extends React.Component<INotificationListProps> {
public render() {
const { notifications, onEditTag, onDeleteTag } = this.props;

return (
<div className="notification-list">
{notifications.map((notification: INotification, idx: number) => {
const {
entityTag: {
lastModified,
value: { title, message, tagline },
},
entityTags: { lastModified },
} = notification;

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { find, flatten, uniq, without } from 'lodash';

import { Application } from 'core/application/application.model';
import { CollapsibleSectionStateCache } from 'core/cache';
import { EntityNotifications } from 'core/entityTag/notifications/EntityNotifications';
import { Execution } from '../execution/Execution';
import { IExecution, IExecutionGroup, IExecutionTrigger, IPipeline, IPipelineCommand } from 'core/domain';
import { NextRunTag } from 'core/pipeline/triggers/NextRunTag';
Expand Down Expand Up @@ -275,6 +276,14 @@ export class ExecutionGroup extends React.Component<IExecutionGroupProps, IExecu
</span>
)}
</h4>
<EntityNotifications
entity={pipelineConfig}
application={this.props.application}
entity-type="pipeline"
hOffsetPercent="20%"
placement="top"
onUpdate={() => this.props.application.refresh()}
/>
{this.state.canConfigure && (
<div className="text-right execution-group-actions">
{pipelineConfig && <TriggersTag pipeline={pipelineConfig} />}
Expand Down
Loading

0 comments on commit 7a4b0cd

Please sign in to comment.