Skip to content

Commit bcebc72

Browse files
micheldavidJustinBeckwith
authored andcommitted
DLP sample: Add autoPopulateTimespan option for creating job triggers. (#64)
1 parent 9bab80f commit bcebc72

12 files changed

+66
-19
lines changed

dlp/.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Test outputs
2+
*.actual.png
3+
*.actual.csv

dlp/package.json

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
"devDependencies": {
2222
"@google-cloud/nodejs-repo-tools": "^2.3.0",
2323
"ava": "^0.25.0",
24+
"pixelmatch": "^4.0.2",
25+
"pngjs": "^3.3.3",
2426
"uuid": "^3.3.2"
2527
}
2628
}

dlp/system-test/deid.test.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ test(`should handle FPE decryption errors`, async t => {
123123

124124
// deidentify_date_shift
125125
test(`should date-shift a CSV file`, async t => {
126-
const outputCsvFile = path.join(__dirname, 'dates.result.csv');
126+
const outputCsvFile = 'dates.actual.csv';
127127
const output = await tools.runAsync(
128128
`${cmd} deidDateShift "${csvFile}" "${outputCsvFile}" ${dateShiftAmount} ${dateShiftAmount} ${dateFields}`,
129129
cwd
@@ -138,9 +138,9 @@ test(`should date-shift a CSV file`, async t => {
138138
});
139139

140140
test(`should date-shift a CSV file using a context field`, async t => {
141-
const outputCsvFile = path.join(__dirname, 'dates-context.result.csv');
142-
const correctResultFile =
143-
'system-test/resources/date-shift-context.correct.csv';
141+
const outputCsvFile = 'dates-context.actual.csv';
142+
const expectedCsvFile =
143+
'system-test/resources/date-shift-context.expected.csv';
144144
const output = await tools.runAsync(
145145
`${cmd} deidDateShift "${csvFile}" "${outputCsvFile}" ${dateShiftAmount} ${dateShiftAmount} ${dateFields} -f ${csvContextField} -n ${keyName} -w ${wrappedKey}`,
146146
cwd
@@ -150,7 +150,7 @@ test(`should date-shift a CSV file using a context field`, async t => {
150150
);
151151
t.is(
152152
fs.readFileSync(outputCsvFile).toString(),
153-
fs.readFileSync(correctResultFile).toString()
153+
fs.readFileSync(expectedCsvFile).toString()
154154
);
155155
});
156156

dlp/system-test/redact.test.js

+40-11
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ const path = require('path');
1919
const test = require('ava');
2020
const fs = require('fs');
2121
const tools = require('@google-cloud/nodejs-repo-tools');
22+
const PNG = require('pngjs').PNG;
23+
const pixelmatch = require('pixelmatch');
2224

2325
const cmd = 'node redact.js';
2426
const cwd = path.join(__dirname, `..`);
@@ -28,6 +30,33 @@ const testResourcePath = 'system-test/resources';
2830

2931
test.before(tools.checkCredentials);
3032

33+
function readImage(filePath) {
34+
return new Promise((resolve, reject) => {
35+
fs.createReadStream(filePath)
36+
.pipe(new PNG())
37+
.on('error', reject)
38+
.on('parsed', function() {
39+
resolve(this);
40+
});
41+
});
42+
}
43+
44+
async function getImageDiffPercentage(image1Path, image2Path) {
45+
let image1 = await readImage(image1Path);
46+
let image2 = await readImage(image2Path);
47+
let diff = new PNG({width: image1.width, height: image1.height});
48+
49+
const diffPixels = pixelmatch(
50+
image1.data,
51+
image2.data,
52+
diff.data,
53+
image1.width,
54+
image1.height
55+
);
56+
return diffPixels / (diff.width * diff.height);
57+
}
58+
59+
// redact_text
3160
test(`should redact a single sensitive data type from a string`, async t => {
3261
const output = await tools.runAsync(
3362
`${cmd} string "My email is [email protected]" -t EMAIL_ADDRESS`,
@@ -56,33 +85,33 @@ test(`should handle string with no sensitive data`, async t => {
5685
test(`should redact a single sensitive data type from an image`, async t => {
5786
const testName = `redact-single-type`;
5887
const output = await tools.runAsync(
59-
`${cmd} image ${testImage} ${testName}.result.png -t PHONE_NUMBER`,
88+
`${cmd} image ${testImage} ${testName}.actual.png -t PHONE_NUMBER`,
6089
cwd
6190
);
6291

6392
t.regex(output, /Saved image redaction results to path/);
6493

65-
const correct = fs.readFileSync(
66-
`${testResourcePath}/${testName}.correct.png`
94+
const difference = await getImageDiffPercentage(
95+
`${testName}.actual.png`,
96+
`${testResourcePath}/${testName}.expected.png`
6797
);
68-
const result = fs.readFileSync(`${testName}.result.png`);
69-
t.deepEqual(correct, result);
98+
t.true(difference < 0.03);
7099
});
71100

72101
test(`should redact multiple sensitive data types from an image`, async t => {
73102
const testName = `redact-multiple-types`;
74103
const output = await tools.runAsync(
75-
`${cmd} image ${testImage} ${testName}.result.png -t PHONE_NUMBER EMAIL_ADDRESS`,
104+
`${cmd} image ${testImage} ${testName}.actual.png -t PHONE_NUMBER EMAIL_ADDRESS`,
76105
cwd
77106
);
78107

79108
t.regex(output, /Saved image redaction results to path/);
80109

81-
const correct = fs.readFileSync(
82-
`${testResourcePath}/${testName}.correct.png`
110+
const difference = await getImageDiffPercentage(
111+
`${testName}.actual.png`,
112+
`${testResourcePath}/${testName}.expected.png`
83113
);
84-
const result = fs.readFileSync(`${testName}.result.png`);
85-
t.deepEqual(correct, result);
114+
t.true(difference < 0.03);
86115
});
87116

88117
test(`should report info type errors`, async t => {
@@ -95,7 +124,7 @@ test(`should report info type errors`, async t => {
95124

96125
test(`should report image redaction handling errors`, async t => {
97126
const output = await tools.runAsync(
98-
`${cmd} image ${testImage} nonexistent.result.png -t BAD_TYPE`,
127+
`${cmd} image ${testImage} output.png -t BAD_TYPE`,
99128
cwd
100129
);
101130
t.regex(output, /Error in redactImage/);
Binary file not shown.

dlp/system-test/risk.test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ const uniqueField = 'Name';
2929
const repeatedField = 'Mystery';
3030
const numericField = 'Age';
3131
const stringBooleanField = 'Gender';
32-
const testProjectId = 'nodejs-docs-samples';
32+
const testProjectId = process.env.GCLOUD_PROJECT;
3333

3434
test.before(tools.checkCredentials);
3535

dlp/system-test/templates.test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ test.serial(`should create template`, async t => {
4242
});
4343

4444
test(`should handle template creation errors`, async t => {
45-
const output = await tools.runAsync(`${cmd} create -t BAD_INFOTYPE`);
45+
const output = await tools.runAsync(`${cmd} create -i invalid_template#id`);
4646
t.regex(output, /Error in createInspectTemplate/);
4747
});
4848

dlp/system-test/triggers.test.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ const bucketName = process.env.BUCKET_NAME;
3333

3434
test.serial(`should create a trigger`, async t => {
3535
const output = await tools.runAsync(
36-
`${cmd} create ${bucketName} 1 -n ${triggerName} -m ${minLikelihood} -t ${infoType} -f ${maxFindings} -d "${triggerDisplayName}" -s "${triggerDescription}"`
36+
`${cmd} create ${bucketName} 1 -n ${triggerName} --autoPopulateTimespan \
37+
-m ${minLikelihood} -t ${infoType} -f ${maxFindings} -d "${triggerDisplayName}" -s "${triggerDescription}"`
3738
);
3839
t.true(output.includes(`Successfully created trigger ${fullTriggerName}`));
3940
});

dlp/triggers.js

+12
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ function createTrigger(
2121
displayName,
2222
description,
2323
bucketName,
24+
autoPopulateTimespan,
2425
scanPeriod,
2526
infoTypes,
2627
minLikelihood,
@@ -48,6 +49,9 @@ function createTrigger(
4849
// The name of the bucket to scan.
4950
// const bucketName = 'YOUR-BUCKET';
5051

52+
// Limit scan to new content only.
53+
// const autoPopulateTimespan = true;
54+
5155
// How often to wait between scans, in days (minimum = 1 day)
5256
// const scanPeriod = 1;
5357

@@ -65,6 +69,9 @@ function createTrigger(
6569
cloudStorageOptions: {
6670
fileSet: {url: `gs://${bucketName}/*`},
6771
},
72+
timeSpanConfig: {
73+
enableAutoPopulationOfTimespanConfig: autoPopulateTimespan,
74+
},
6875
};
6976

7077
// Construct job to be triggered
@@ -221,6 +228,10 @@ const cli = require(`yargs`) // eslint-disable-line
221228
default: '',
222229
type: 'string',
223230
},
231+
autoPopulateTimespan: {
232+
default: false,
233+
type: 'boolean',
234+
},
224235
minLikelihood: {
225236
alias: 'm',
226237
default: 'LIKELIHOOD_UNSPECIFIED',
@@ -249,6 +260,7 @@ const cli = require(`yargs`) // eslint-disable-line
249260
opts.displayName,
250261
opts.description,
251262
opts.bucketName,
263+
opts.autoPopulateTimespan,
252264
opts.scanPeriod,
253265
opts.infoTypes,
254266
opts.minLikelihood,

0 commit comments

Comments
 (0)