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

Provide docker commands in command pallet #24

Merged
merged 24 commits into from
Oct 12, 2016
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"args": ["--extensionDevelopmentPath=${workspaceRoot}" ],
"stopOnEntry": false,
"sourceMaps": true,
"outDir": "${workspaceRoot}/",
"outDir": "${workspaceRoot}/out",
"preLaunchTask": "npm"
}
]
Expand Down
72 changes: 72 additions & 0 deletions commands/build-image.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import vscode = require('vscode');


function hasWorkspaceFolder() : boolean {
return vscode.workspace.rootPath ? true : false;
}

function getDockerFileUris(): Thenable<vscode.Uri[]>{
if (!hasWorkspaceFolder()) {
return Promise.resolve(null);
}
return Promise.resolve(vscode.workspace.findFiles('**/[dD]ocker[fF]ile', null, 9999, null));
}

interface Item extends vscode.QuickPickItem {
path: string,
file: string
}

function createItem(uri: vscode.Uri) : Item {
let length = vscode.workspace.rootPath.length;
let label = uri.fsPath.substr(length);
return <Item> {
label: label,
description: null,
path: '.' + label.substr(0, label.length - '/dockerfile'.length),
file: '.' + label
};
}

function computeItems(uris: vscode.Uri[]) : vscode.QuickPickItem[] {
let items : vscode.QuickPickItem[] = [];
for (let i = 0; i < uris.length; i++) {
items.push(createItem(uris[i]));
}
return items;
}

export function buildImage() {
getDockerFileUris().then(function (uris: vscode.Uri[]) {
if (!uris || uris.length == 0) {
vscode.window.showInformationMessage('Couldn\'t find any dockerfile in your workspace.');
} else {
let items: vscode.QuickPickItem[] = computeItems(uris);
vscode.window.showQuickPick(items, { placeHolder: 'Choose Dockerfile to build' }).then(function(selectedItem : Item) {
if (selectedItem) {

let imageName = selectedItem.path.split('/').pop().toLowerCase();
if (imageName === '.') {
imageName = vscode.workspace.rootPath.split('/').pop().toLowerCase();
}

let configOptions: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration('docker');

let defaultRegistryPath = configOptions.get('defaultRegistryPath', '');
if (defaultRegistryPath.length > 0) {
imageName = defaultRegistryPath + '/' + imageName;
}

let defaultRegistry = configOptions.get('defaultRegistry', '');
if (defaultRegistry.length > 0) {
imageName = defaultRegistry + '/' + imageName;
}

let terminal: vscode.Terminal = vscode.window.createTerminal('Docker');
terminal.sendText(`docker build -f ${selectedItem.file} -t ${imageName} ${selectedItem.path}`);
terminal.show();
}
});
}
});
}
63 changes: 63 additions & 0 deletions commands/docker-compose.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import vscode = require('vscode');


function hasWorkspaceFolder() : boolean {
return vscode.workspace.rootPath ? true : false;
}

function getDockerComposeFileUris(): Thenable<vscode.Uri[]>{
if (!hasWorkspaceFolder()) {
return Promise.resolve(null);
}
return Promise.resolve(vscode.workspace.findFiles('{**/[dD]ocker-[cC]ompose.*.yml,**/[dD]ocker-[cC]ompose.yml}', null, 9999, null));
}

interface Item extends vscode.QuickPickItem {
path: string,
file: string
}

function createItem(uri: vscode.Uri) : Item {
let length = vscode.workspace.rootPath.length;
let label = uri.fsPath.substr(length);
let slashIndex = label.lastIndexOf('/');
return <Item> {
label: label,
description: null,
path: '.' + label.substr(0, slashIndex),
file: label.substr(slashIndex + 1)
};
}

function computeItems(uris: vscode.Uri[]) : vscode.QuickPickItem[] {
let items : vscode.QuickPickItem[] = [];
for (let i = 0; i < uris.length; i++) {
items.push(createItem(uris[i]));
}
return items;
}

export function compose(command: string, message: string) {
getDockerComposeFileUris().then(function (uris: vscode.Uri[]) {
if (!uris || uris.length == 0) {
vscode.window.showInformationMessage('Couldn\'t find any docker-compose file in your workspace.');
} else {
let items: vscode.QuickPickItem[] = computeItems(uris);
vscode.window.showQuickPick(items, { placeHolder: `Choose Docker Compose file ${message}` }).then(function(selectedItem : Item) {
if (selectedItem) {
let terminal: vscode.Terminal = vscode.window.createTerminal('Docker Compose');
terminal.sendText(`cd ${selectedItem.path}; docker-compose -f ${selectedItem.file} ${command}`);
terminal.show();
}
});
}
});
}

export function composeUp() {
compose('up', 'to bring up');
}

export function composeDown() {
compose('down', 'to take down');
}
12 changes: 12 additions & 0 deletions commands/open-shell-container.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import vscode = require('vscode');
import {ContainerItem, quickPickContainer} from './utils/quick-pick-container';

export function openShellContainer() {
quickPickContainer().then(function (selectedItem: ContainerItem) {
if (selectedItem) {
let terminal = vscode.window.createTerminal(`sh ${selectedItem.label}`);
terminal.sendText(`docker exec -it ${selectedItem.ids[0]} /bin/sh`);
terminal.show();
}
});
}
12 changes: 12 additions & 0 deletions commands/push-image.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import vscode = require('vscode');
import {ImageItem, quickPickImage} from './utils/quick-pick-image';

export function pushImage() {
quickPickImage().then(function (selectedItem: ImageItem) {
if (selectedItem) {
let terminal = vscode.window.createTerminal(selectedItem.label);
terminal.sendText(`docker push ${selectedItem.label}`);
terminal.show();
};
});
}
15 changes: 15 additions & 0 deletions commands/remove-image.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import {docker} from './utils/docker-endpoint';
import {ImageItem, quickPickImage} from './utils/quick-pick-image';


export function removeImage() {
quickPickImage().then(function (selectedItem: ImageItem) {
if (selectedItem) {
let image = docker.getImage(selectedItem.id);
image.remove({ force: true }, function (err, data) {
// console.log("Removed - error: " + err);
// console.log("Removed - data: " + data);
});
}
});
}
13 changes: 13 additions & 0 deletions commands/showlogs-container.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import vscode = require('vscode');
import {ContainerItem, quickPickContainer} from './utils/quick-pick-container';


export function showLogsContainer() {
quickPickContainer().then(function (selectedItem: ContainerItem) {
if (selectedItem) {
let terminal = vscode.window.createTerminal(selectedItem.label);
terminal.sendText(`docker logs ${selectedItem.ids[0]}`);
terminal.show();
}
});
}
22 changes: 22 additions & 0 deletions commands/start-container.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import vscode = require('vscode');
import {ImageItem, quickPickImage} from './utils/quick-pick-image';


function doStartContainer(interactive: boolean) {
quickPickImage().then(function (selectedItem: ImageItem) {
if (selectedItem) {
let option = interactive ? '-it' : '';
let terminal = vscode.window.createTerminal(selectedItem.label);
terminal.sendText(`docker run ${option} --rm ${selectedItem.label}`);
terminal.show();
}
});
}

export function startContainer() {
doStartContainer(false);
}

export function startContainerInteractive() {
doStartContainer(true);
}
17 changes: 17 additions & 0 deletions commands/stop-container.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {docker} from './utils/docker-endpoint';
import {ContainerItem, quickPickContainer} from './utils/quick-pick-container';


export function stopContainer() {
quickPickContainer(true).then(function (selectedItem: ContainerItem) {
if (selectedItem) {
for (let i = 0; i < selectedItem.ids.length; i++) {
let container = docker.getContainer(selectedItem.ids[i]);
container.stop(function (err, data) {
// console.log("Stopped - error: " + err);
// console.log("Stopped - data: " + data);
});
}
}
});
}
47 changes: 47 additions & 0 deletions commands/utils/docker-endpoint.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import * as Docker from 'dockerode';


class DockerClient {

private endPoint:Docker;

constructor() {
if (process.platform === 'win32') {
this.endPoint = new Docker({ socketPath: "//./pipe/docker_engine" });
} else {
this.endPoint = new Docker({ socketPath: '/var/run/docker.sock' });
}
}

public getContainerDescriptors(): Thenable<Docker.ContainerDesc[]>{
return new Promise((resolve, reject) => {
this.endPoint.listContainers((err, containers) => {
if (err) {
return reject(err);
}
return resolve(containers);
});
});
};

public getImageDescriptors(): Thenable<Docker.ImageDesc[]>{
return new Promise((resolve, reject) => {
this.endPoint.listImages((err, images) => {
if (err) {
return reject(err);
}
return resolve(images);
});
});
};

public getContainer(id: string): Docker.Container {
return this.endPoint.getContainer(id);
}

public getImage(id:string): Docker.Image {
return this.endPoint.getImage(id);
}
}

export const docker = new DockerClient();
50 changes: 50 additions & 0 deletions commands/utils/quick-pick-container.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import * as Docker from 'dockerode';
import {docker} from './docker-endpoint';
import vscode = require('vscode');


export interface ContainerItem extends vscode.QuickPickItem {
ids: string[]
}

function createItem(container: Docker.ContainerDesc) : ContainerItem {
return <ContainerItem> {
label: container.Image,
description: container.Status,
ids: [ container.Id ]
};
}

function computeItems(containers: Docker.ContainerDesc[], includeAll: boolean) : ContainerItem[] {

let allIds: string[] = [];

let items : ContainerItem[] = [];
for (let i = 0; i < containers.length; i++) {
let item = createItem(containers[i]);
allIds.push(item.ids[0]);
items.push(item);
}

if (includeAll && allIds.length > 0) {
items.unshift(<ContainerItem> {
label: 'All Containers',
description: 'Stops all running containers',
ids: allIds
});
}

return items;
}

export function quickPickContainer(includeAll: boolean = false) : Thenable<ContainerItem>{
return docker.getContainerDescriptors().then(containers => {
if (!containers || containers.length == 0) {
vscode.window.showInformationMessage('There are no running docker containers.');
return Promise.resolve(null);
} else {
let items: ContainerItem[] = computeItems(containers, includeAll);
return vscode.window.showQuickPick(items, { placeHolder: 'Choose Container' });
}
});
}
37 changes: 37 additions & 0 deletions commands/utils/quick-pick-image.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import * as Docker from 'dockerode';
import {docker} from './docker-endpoint';
import vscode = require('vscode');



export interface ImageItem extends vscode.QuickPickItem {
id: string,
}

function createItem(image: Docker.ImageDesc) : ImageItem {
return <ImageItem> {
label: image.RepoTags[0] || '<none>',
description: null,
id: image.Id
};
}

function computeItems(images: Docker.ImageDesc[]) : ImageItem[] {
let items : ImageItem[] = [];
for (let i = 0; i < images.length; i++) {
items.push(createItem(images[i]));
}
return items;
}

export function quickPickImage() : Thenable<ImageItem> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to allow removing all images in one command, similarly to how the stop container command works? That would be nice to not have to remember how to type docker rmi $(docker images -qa)!

return docker.getImageDescriptors().then(images => {
if (!images || images.length == 0) {
vscode.window.showInformationMessage('There are no docker images yet. Try Build first.');
return Promise.resolve(null);
} else {
let items: ImageItem[] = computeItems(images);
return vscode.window.showQuickPick(items, { placeHolder: 'Choose image' });
}
});
}