Skip to content

Commit

Permalink
Users/jikuma/imagename (#6278)
Browse files Browse the repository at this point in the history
* Docker imagename fix

* docker image name and telemetry changes

* kubernetes recompile with new docker-common

* changed ui

* rename task input
  • Loading branch information
jikuma authored Jan 24, 2018
1 parent 9440f08 commit 3812732
Show file tree
Hide file tree
Showing 19 changed files with 86 additions and 19 deletions.
7 changes: 1 addition & 6 deletions Tasks/Common/docker-common/containerimageutils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,8 @@ export function imageNameWithoutTag(imageName: string): string {
return generateValidImageName(endIndex < 0 ? imageName : imageName.substr(0, endIndex));
}

export function getImageName(): string {
var imageName = tl.getInput("imageName", true);
return generateValidImageName(imageName);
}

export function generateValidImageName(imageName: string): string {
imageName = imageName.toLowerCase();
imageName = imageName.replace(/ /g,"");
return imageName;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export default class ACRAuthenticationTokenProvider extends AuthenticationTokenP
public getAuthenticationToken(): RegistryAuthenticationToken
{
if(this.registryURL && this.endpointName) {
return new RegistryAuthenticationToken(tl.getEndpointAuthorizationParameter(this.endpointName, 'serviceprincipalid', true), tl.getEndpointAuthorizationParameter(this.endpointName, 'serviceprincipalkey', true), this.registryURL, "ServicePrincipal@AzureRM", "azure/vsts");
return new RegistryAuthenticationToken(tl.getEndpointAuthorizationParameter(this.endpointName, 'serviceprincipalid', true), tl.getEndpointAuthorizationParameter(this.endpointName, 'serviceprincipalkey', true), this.registryURL, "ServicePrincipal@AzureRM", this.getXMetaSourceClient());
}

return null;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
"use strict";

import * as tl from "vsts-task-lib/task";
import * as url from "url";

import RegistryAuthenticationToken from "./registryauthenticationtoken"

export abstract class AuthenticationTokenProvider {
// get registry login creds
public abstract getAuthenticationToken(): RegistryAuthenticationToken

protected getXMetaSourceClient(): string {
var collectionUri: string = tl.getVariable('System.TeamFoundationCollectionUri');
var collectionUrlObject = url.parse(collectionUri);
if(collectionUrlObject.hostname.toUpperCase().endsWith(".VISUALSTUDIO.COM")) {
return "VSTS";
}

return "TFS";
}
}

export default AuthenticationTokenProvider;
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export default class GenericAuthenticationTokenProvider extends AuthenticationTo
public getAuthenticationToken(): RegistryAuthenticationToken {

if(this.registryAuth) {
return new RegistryAuthenticationToken(this.registryAuth["username"], this.registryAuth["password"], this.registryAuth["registry"], this.registryAuth["email"], "generic/vsts");
return new RegistryAuthenticationToken(this.registryAuth["username"], this.registryAuth["password"], this.registryAuth["registry"], this.registryAuth["email"], this.getXMetaSourceClient());
}

return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@
"loc.input.help.customCommand": "Docker command to execute, with arguments. For example, 'rmi -f image-name' to force remove an image.",
"loc.input.label.dockerHostEndpoint": "Docker Host Connection",
"loc.input.help.dockerHostEndpoint": "Select a Docker host connection. Defaults to the agent's host.",
"loc.input.label.enforceDockerNamingConvention": "Force image name to follow Docker naming convention",
"loc.input.help.enforceDockerNamingConvention": "If enabled docker image name will be modified to follow Docker naming convention. Converts upper case character to lower case and removes spaces in image name.",
"loc.input.label.cwd": "Working Directory",
"loc.input.help.cwd": "Working directory for the Docker command.",
"loc.messages.ContainerPatternFound": "Pattern found in docker filepath parameter",
Expand Down
19 changes: 19 additions & 0 deletions Tasks/Docker/Tests/L0.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ describe('Docker Suite', function() {
delete process.env[shared.TestEnvVars.includeLatestTag];
delete process.env[shared.TestEnvVars.imageName];
delete process.env[shared.TestEnvVars.additionalImageTags];
delete process.env[shared.TestEnvVars.enforceDockerNamingConvention];
});
after(function () {
});
Expand All @@ -41,6 +42,7 @@ describe('Docker Suite', function() {
let tr : ttm.MockTestRunner = new ttm.MockTestRunner(tp);
process.env[shared.TestEnvVars.action] = shared.ActionTypes.buildImage;
process.env[shared.TestEnvVars.imageName] = 'test/Te st:2';
process.env[shared.TestEnvVars.enforceDockerNamingConvention] = 'true';
tr.run();

assert(tr.invokedToolCount == 1, 'should have invoked tool one times. actual: ' + tr.invokedToolCount);
Expand All @@ -51,12 +53,29 @@ describe('Docker Suite', function() {
done();
});

it('Runs fails for docker build for invalid image name and modify image name false', (done:MochaDone) => {
let tp = path.join(__dirname, 'TestSetup.js');
let tr : ttm.MockTestRunner = new ttm.MockTestRunner(tp);
process.env[shared.TestEnvVars.action] = shared.ActionTypes.buildImage;
process.env[shared.TestEnvVars.imageName] = 'test/Te st:2';
process.env[shared.TestEnvVars.enforceDockerNamingConvention] = 'false';
tr.run();

assert(tr.invokedToolCount == 1, 'should have invoked tool one times. actual: ' + tr.invokedToolCount);
assert(tr.stderr.length == 1 || tr.errorIssues.length, 'should have written to stderror');
assert(tr.failed, 'task should have failed');
assert(tr.stdout.indexOf(`test/Te st:2 not valid imagename`) != -1, "docker build should fail");
console.log(tr.stderr);
done();
});

it('Runs successfully for docker build for invalid image name and additional image tag', (done:MochaDone) => {
let tp = path.join(__dirname, 'TestSetup.js');
let tr : ttm.MockTestRunner = new ttm.MockTestRunner(tp);
process.env[shared.TestEnvVars.action] = shared.ActionTypes.buildImage;
process.env[shared.TestEnvVars.imageName] = 'test/Test:2';
process.env[shared.TestEnvVars.additionalImageTags] = '6';
process.env[shared.TestEnvVars.enforceDockerNamingConvention] = 'true';
tr.run();

assert(tr.invokedToolCount == 1, 'should have invoked tool one times. actual: ' + tr.invokedToolCount);
Expand Down
6 changes: 6 additions & 0 deletions Tasks/Docker/Tests/TestSetup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@ tr.setInput('qualifyImageName', process.env[shared.TestEnvVars.qualifyImageName]
tr.setInput('azureSubscriptionEndpoint', 'AzureRMSpn');
tr.setInput('azureContainerRegistry', '{"loginServer":"ajgtestacr1.azurecr.io", "id" : "/subscriptions/c00d16c7-6c1f-4c03-9be1-6934a4c49682/resourcegroups/ajgtestacr1rg/providers/Microsoft.ContainerRegistry/registries/ajgtestacr1"}')
tr.setInput('additionalImageTags', process.env[shared.TestEnvVars.additionalImageTags] || '');
tr.setInput('enforceDockerNamingConvention', process.env[shared.TestEnvVars.enforceDockerNamingConvention]);

console.log("Inputs have been set");

process.env["RELEASE_RELEASENAME"] = "Release-1";
process.env["SYSTEM_DEFAULTWORKINGDIRECTORY"] = DefaultWorkingDirectory;
process.env["SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"] = "https://abc.visualstudio.com/";
process.env["ENDPOINT_AUTH_dockerhubendpoint"] = "{\"parameters\":{\"username\":\"test\", \"password\":\"regpassword\", \"email\":\"[email protected]\",\"registry\":\"https://index.docker.io/v1/\"},\"scheme\":\"UsernamePassword\"}";
process.env["ENDPOINT_AUTH_SCHEME_AzureRMSpn"] = "ServicePrincipal";
process.env["ENDPOINT_AUTH_PARAMETER_AzureRMSpn_SERVICEPRINCIPALID"] = "spId";
Expand Down Expand Up @@ -72,6 +74,10 @@ a.exec[`docker build -f ${DockerFilePath} -t test/test:2`] = {
"code": 0,
"stdout": "successfully build test/test:2 image"
};
a.exec[`docker build -f ${DockerFilePath} -t test/Te st:2`] = {
"code": 1,
"stdout": "test/Te st:2 not valid imagename"
};
a.exec[`docker build -f ${DockerFilePath} -t test/test:2 -t test/test`] = {
"code": 0,
"stdout": "successfully build test/test image with latest tag"
Expand Down
3 changes: 2 additions & 1 deletion Tasks/Docker/Tests/TestShared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ export let TestEnvVars = {
qualifyImageName: "__qualifyImageName__",
includeLatestTag: "__includeLatestTag__",
imageName: "__imageName__",
additionalImageTags: "__additionalImageTags__"
additionalImageTags: "__additionalImageTags__",
enforceDockerNamingConvention: "__enforceDockerNamingConvention__"
};

export let OperatingSystems = {
Expand Down
2 changes: 1 addition & 1 deletion Tasks/Docker/containerbuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export function run(connection: ContainerConnection): any {
command.arg(["--build-arg", buildArgument]);
});

var imageName = imageUtils.getImageName();
var imageName = utils.getImageName();
var qualifyImageName = tl.getBoolInput("qualifyImageName");
if (qualifyImageName) {
imageName = connection.qualifyImageName(imageName);
Expand Down
2 changes: 1 addition & 1 deletion Tasks/Docker/containerpush.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export function run(connection: ContainerConnection): any {
if (useMultiImageMode) {
imageNames = utils.getImageNames();
} else {
imageNames = [imageUtils.getImageName()];
imageNames = [utils.getImageName()];
}

let imageMappings = utils.getImageMappings(connection, imageNames);
Expand Down
4 changes: 2 additions & 2 deletions Tasks/Docker/containerrun.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ export function run(connection: ContainerConnection): any {
if (workDir) {
command.arg(["-w", workDir]);
}

var imageName = imageUtils.getImageName();
var imageName = utils.getImageName();
var qualifyImageName = tl.getBoolInput("qualifyImageName");
if (qualifyImageName) {
imageName = connection.qualifyImageName(imageName);
Expand Down
11 changes: 10 additions & 1 deletion Tasks/Docker/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"version": {
"Major": 0,
"Minor": 3,
"Patch": 5
"Patch": 6
},
"demands": [],
"preview": "false",
Expand Down Expand Up @@ -277,6 +277,15 @@
"helpMarkDown": "Select a Docker host connection. Defaults to the agent's host.",
"groupName": "advanced"
},
{
"name": "enforceDockerNamingConvention",
"type": "boolean",
"label": "Force image name to follow Docker naming convention",
"required": false,
"defaultValue": "true",
"helpMarkDown": "If enabled docker image name will be modified to follow Docker naming convention. Converts upper case character to lower case and removes spaces in image name.",
"groupName": "advanced"
},
{
"name": "cwd",
"aliases": ["workingDirectory"],
Expand Down
11 changes: 10 additions & 1 deletion Tasks/Docker/task.loc.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"version": {
"Major": 0,
"Minor": 3,
"Patch": 5
"Patch": 6
},
"demands": [],
"preview": "false",
Expand Down Expand Up @@ -281,6 +281,15 @@
"helpMarkDown": "ms-resource:loc.input.help.dockerHostEndpoint",
"groupName": "advanced"
},
{
"name": "enforceDockerNamingConvention",
"type": "boolean",
"label": "ms-resource:loc.input.label.enforceDockerNamingConvention",
"required": false,
"defaultValue": "true",
"helpMarkDown": "ms-resource:loc.input.help.enforceDockerNamingConvention",
"groupName": "advanced"
},
{
"name": "cwd",
"aliases": [
Expand Down
13 changes: 12 additions & 1 deletion Tasks/Docker/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,23 @@ import * as imageUtils from "docker-common/containerimageutils";

export function getImageNames(): string[] {
let imageNamesFilePath = tl.getPathInput("imageNamesPath", /* required */ true, /* check exists */ true);
var enforceDockerNamingConvention = tl.getBoolInput("enforceDockerNamingConvention");
let imageNames = fs.readFileSync(imageNamesFilePath, "utf-8").trim().replace("\r\n", "\n").split("\n");
if (!imageNames.length) {
throw new Error(tl.loc("NoImagesInImageNamesFile", imageNamesFilePath));
}

return imageNames.map(n => imageUtils.generateValidImageName(n));
return imageNames.map(n => (enforceDockerNamingConvention === true)? imageUtils.generateValidImageName(n): n);
}

export function getImageName(): string {
var enforceDockerNamingConvention = tl.getBoolInput("enforceDockerNamingConvention");
var imageName = tl.getInput("imageName", true);
if(enforceDockerNamingConvention === true) {
return imageUtils.generateValidImageName(imageName);
}

return imageName;
}

export function getImageMappings(connection: ContainerConnection, imageNames: string[]): ImageMapping[] {
Expand Down
1 change: 1 addition & 0 deletions Tasks/DockerCompose/Tests/L0Linux.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ console.log("Inputs have been set");

process.env["RELEASE_RELEASENAME"] = "Release-1";
process.env["SYSTEM_DEFAULTWORKINGDIRECTORY"] = DefaultWorkingDirectory;
process.env["SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"] = "https://abc.visualstudio.com/";
process.env["ENDPOINT_AUTH_dockerhubendpoint"] = "{\"parameters\":{\"username\":\"test\", \"password\":\"regpassword\", \"email\":\"[email protected]\",\"registry\":\"https://index.docker.io/v1/\"},\"scheme\":\"UsernamePassword\"}";
process.env["ENDPOINT_AUTH_SCHEME_AzureRMSpn"] = "ServicePrincipal";
process.env["ENDPOINT_AUTH_PARAMETER_AzureRMSpn_SERVICEPRINCIPALID"] = "spId";
Expand Down
1 change: 1 addition & 0 deletions Tasks/DockerCompose/Tests/L0Windows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ console.log("Inputs have been set");

process.env["RELEASE_RELEASENAME"] = "Release-1";
process.env["SYSTEM_DEFAULTWORKINGDIRECTORY"] = DefaultWorkingDirectory;
process.env["SYSTEM_TEAMFOUNDATIONCOLLECTIONURI"] = "https://abc.visualstudio.com/";
process.env["ENDPOINT_AUTH_dockerhubendpoint"] = "{\"parameters\":{\"username\":\"test\", \"password\":\"regpassword\", \"email\":\"[email protected]\",\"registry\":\"https://index.docker.io/v1/\"},\"scheme\":\"UsernamePassword\"}";
process.env["ENDPOINT_AUTH_SCHEME_AzureRMSpn"] = "ServicePrincipal";
process.env["ENDPOINT_AUTH_PARAMETER_AzureRMSpn_SERVICEPRINCIPALID"] = "spId";
Expand Down
2 changes: 1 addition & 1 deletion Tasks/DockerCompose/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"version": {
"Major": 0,
"Minor": 4,
"Patch": 11
"Patch": 12
},
"demands": [],
"preview": "false",
Expand Down
2 changes: 1 addition & 1 deletion Tasks/Kubernetes/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"version": {
"Major": 0,
"Minor": 1,
"Patch": 10
"Patch": 11
},
"demands": [],
"preview": "false",
Expand Down
2 changes: 1 addition & 1 deletion Tasks/Kubernetes/task.loc.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"version": {
"Major": 0,
"Minor": 1,
"Patch": 10
"Patch": 11
},
"demands": [],
"preview": "false",
Expand Down

0 comments on commit 3812732

Please sign in to comment.