Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Group containers by compose project name #1876

Merged
merged 3 commits into from
Apr 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
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
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1572,6 +1572,7 @@
"default": "None",
"description": "%vscode-docker.config.docker.containers.groupBy%",
"enum": [
"Compose Project Name",
"ContainerId",
"ContainerName",
"CreatedTime",
Expand Down Expand Up @@ -1599,6 +1600,7 @@
"items": {
"type": "string",
"enum": [
"Compose Project Name",
ravipal marked this conversation as resolved.
Show resolved Hide resolved
"ContainerId",
"ContainerName",
"CreatedTime",
Expand All @@ -1621,6 +1623,7 @@
"default": "FullTag",
"description": "%vscode-docker.config.docker.containers.label%",
"enum": [
"Compose Project Name",
"ContainerId",
"ContainerName",
"CreatedTime",
Expand Down
8 changes: 4 additions & 4 deletions src/tree/LocalRootTreeItemBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ export abstract class LocalRootTreeItemBase<TItem extends ILocalItem, TProperty
public sortBySetting: CommonSortBy;
public labelSetting: TProperty;
public descriptionSetting: TProperty[];
protected failedToConnect: boolean = false;

private _currentItems: TItem[] | undefined;
private _itemsFromPolling: TItem[] | undefined;
private _failedToConnect: boolean = false;

public get contextValue(): string {
return this.treePrefix;
Expand Down Expand Up @@ -103,10 +103,10 @@ export abstract class LocalRootTreeItemBase<TItem extends ILocalItem, TProperty
try {
this._currentItems = this._itemsFromPolling || await this.getSortedItems();
this._itemsFromPolling = undefined;
this._failedToConnect = false;
this.failedToConnect = false;
} catch (error) {
this._currentItems = undefined;
this._failedToConnect = true;
this.failedToConnect = true;
context.telemetry.properties.failedToConnect = 'true';
return this.getDockerErrorTreeItems(context, error);
}
Expand Down Expand Up @@ -137,7 +137,7 @@ export abstract class LocalRootTreeItemBase<TItem extends ILocalItem, TProperty
}

public compareChildrenImpl(ti1: AzExtTreeItem, ti2: AzExtTreeItem): number {
if (this._failedToConnect) {
if (this.failedToConnect) {
return 0; // children are already sorted
} else {
if (ti1 instanceof this.childGroupType && ti2 instanceof this.childGroupType) {
Expand Down
1 change: 1 addition & 0 deletions src/tree/containers/ContainerGroupTreeItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export class ContainerGroupTreeItem extends LocalGroupTreeItemBase<ILocalContain
break;
case 'Ports':
case 'Status':
case 'Compose Project Name':
icon = 'applicationGroup';
break;
case 'State':
Expand Down
6 changes: 4 additions & 2 deletions src/tree/containers/ContainerProperties.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
* Licensed under the MIT License. See LICENSE.md in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { localize } from "../../localize";
import { getThemedIconPath, IconPath } from "../IconPath";
import { imageProperties, ImageProperty } from "../images/ImageProperties";
import { ITreePropertyInfo } from "../settings/ITreeSettingInfo";

export type ContainerProperty = ImageProperty | 'ContainerId' | 'ContainerName' | 'Networks' | 'Ports' | 'State' | 'Status';
export type ContainerProperty = ImageProperty | 'Compose Project Name' | 'ContainerId' | 'ContainerName' | 'Networks' | 'Ports' | 'State' | 'Status';

export const containerProperties: ITreePropertyInfo<ContainerProperty>[] = [
...imageProperties,
Expand All @@ -16,7 +17,8 @@ export const containerProperties: ITreePropertyInfo<ContainerProperty>[] = [
{ property: 'Networks', exampleValue: 'mybridge_network' },
{ property: 'Ports', exampleValue: '8080' },
{ property: 'State', exampleValue: 'exited' },
{ property: 'Status', exampleValue: 'Exited (0) 2 hours ago' }
{ property: 'Status', exampleValue: 'Exited (0) 2 hours ago' },
{ property: 'Compose Project Name', description: localize('vscode-docker.tree.containers.properties.composeProjectName', 'Value used to associate containers launched by a \'docker-compose up\' command') },
];

export function getContainerStateIcon(state: string): IconPath {
Expand Down
22 changes: 21 additions & 1 deletion src/tree/containers/ContainersTreeItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { ITreeArraySettingInfo, ITreeSettingInfo } from "../settings/ITreeSettin
import { ContainerGroupTreeItem } from "./ContainerGroupTreeItem";
import { containerProperties, ContainerProperty } from "./ContainerProperties";
import { ContainerTreeItem } from "./ContainerTreeItem";
import { ILocalContainerInfo, LocalContainerInfo } from "./LocalContainerInfo";
import { ILocalContainerInfo, LocalContainerInfo, NonComposeGroupName } from "./LocalContainerInfo";

export class ContainersTreeItem extends LocalRootTreeItemBase<ILocalContainerInfo, ContainerProperty> {
public treePrefix: string = 'containers';
Expand Down Expand Up @@ -67,8 +67,28 @@ export class ContainersTreeItem extends LocalRootTreeItemBase<ILocalContainerInf
return item.state;
case 'Status':
return item.status;
case 'Compose Project Name':
return item.composeProjectName;
default:
return getImagePropertyValue(item, property);
}
}

public compareChildrenImpl(ti1: ContainerTreeItem, ti2: ContainerTreeItem): number {
// Override the sorting behavior to keep the non compose group at the bottom when
// grouped by compose project name.
if (this.failedToConnect) {
return 0; // children are already sorted
}
if (this.groupBySetting === 'Compose Project Name'
ravipal marked this conversation as resolved.
Show resolved Hide resolved
&& ti1 instanceof this.childGroupType && ti2 instanceof this.childGroupType
&& (ti1.label === NonComposeGroupName || ti2.label === NonComposeGroupName)) {
if (ti1.label === ti2.label) {
return 0;
} else {
return ti1.label === NonComposeGroupName ? 1 : -1;
}
}
return super.compareChildrenImpl(ti1, ti2);
}
}
15 changes: 15 additions & 0 deletions src/tree/containers/LocalContainerInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/

import { ContainerInfo } from "dockerode";
import { localize } from "../../localize";
import { ILocalItem } from "../LocalRootTreeItemBase";

/**
Expand All @@ -18,8 +19,10 @@ export interface ILocalContainerInfo extends ILocalItem {
ports: number[];
state: string;
status: string;
composeProjectName: string;
}

export const NonComposeGroupName = localize('vscode-docker.tree.containers.otherContainers', 'Other Containers');
/**
* Wrapper class for Dockerode item, which has inconsistent names/types
*/
Expand Down Expand Up @@ -75,6 +78,18 @@ export class LocalContainerInfo implements ILocalContainerInfo {
return this.data.Status;
}

public get composeProjectName(): string {
const labels = Object.keys(this.data.Labels)
.map(label => ({ label: label, value: this.data.Labels[label] }));

const composeProject = labels.find(l => l.label === 'com.docker.compose.project');
if (composeProject) {
return composeProject.value;
} else {
return NonComposeGroupName;
}
}

public get treeId(): string {
// include state in treeId so that auto-refresh will detect and show a new icon when state changes
return this.containerId + this.state;
Expand Down