2015-09-17 19:58:45 +08:00
|
|
|
require('../../support/test_helper');
|
2015-03-24 17:38:14 +08:00
|
|
|
|
2015-01-26 22:02:28 +08:00
|
|
|
var assert = require('../../support/assert');
|
|
|
|
var redis = require('redis');
|
2015-03-24 17:38:14 +08:00
|
|
|
var step = require('step');
|
2015-04-27 23:43:46 +08:00
|
|
|
var FastlyPurge = require('fastly-purge');
|
2015-01-26 22:02:28 +08:00
|
|
|
|
|
|
|
var NamedMapsCacheEntry = require(__dirname + '/../../../lib/cartodb/cache/model/named_maps_entry');
|
2015-07-05 02:41:22 +08:00
|
|
|
var CartodbWindshaft = require(__dirname + '/../../../lib/cartodb/server');
|
2015-01-26 22:02:28 +08:00
|
|
|
|
|
|
|
|
2015-03-30 23:51:17 +08:00
|
|
|
describe('templates surrogate keys', function() {
|
2015-01-26 22:02:28 +08:00
|
|
|
|
2015-01-30 23:50:06 +08:00
|
|
|
var redisClient = redis.createClient(global.environment.redis.port);
|
|
|
|
|
2015-07-05 02:41:22 +08:00
|
|
|
var serverOptions = require('../../../lib/cartodb/server_options');
|
|
|
|
|
2015-01-30 23:50:06 +08:00
|
|
|
// Enable Varnish purge for tests
|
2015-07-05 02:41:22 +08:00
|
|
|
var varnishHost = serverOptions.varnish_host;
|
|
|
|
serverOptions.varnish_host = '127.0.0.1';
|
|
|
|
var varnishPurgeEnabled = serverOptions.varnish_purge_enabled;
|
|
|
|
serverOptions.varnish_purge_enabled = true;
|
2015-01-30 23:50:06 +08:00
|
|
|
|
2015-07-05 02:41:22 +08:00
|
|
|
var fastlyConfig = serverOptions.fastly;
|
2015-04-27 23:43:46 +08:00
|
|
|
var FAKE_FASTLY_API_KEY = 'fastly-api-key';
|
|
|
|
var FAKE_FASTLY_SERVICE_ID = 'fake-service-id';
|
2015-07-05 02:41:22 +08:00
|
|
|
serverOptions.fastly = {
|
2015-04-27 23:43:46 +08:00
|
|
|
enabled: true,
|
|
|
|
// the fastly api key
|
|
|
|
apiKey: FAKE_FASTLY_API_KEY,
|
|
|
|
// the service that will get surrogate key invalidation
|
|
|
|
serviceId: FAKE_FASTLY_SERVICE_ID
|
|
|
|
};
|
|
|
|
|
2015-01-30 23:50:06 +08:00
|
|
|
var server = new CartodbWindshaft(serverOptions);
|
2015-01-26 22:02:28 +08:00
|
|
|
|
|
|
|
var templateOwner = 'localhost',
|
|
|
|
templateName = 'acceptance',
|
2015-04-23 17:29:55 +08:00
|
|
|
expectedTemplateId = templateName,
|
2015-01-26 22:02:28 +08:00
|
|
|
template = {
|
|
|
|
version: '0.0.1',
|
|
|
|
name: templateName,
|
|
|
|
auth: {
|
|
|
|
method: 'open'
|
|
|
|
},
|
|
|
|
layergroup: {
|
|
|
|
version: '1.2.0',
|
|
|
|
layers: [
|
|
|
|
{
|
|
|
|
options: {
|
|
|
|
sql: 'select 1 cartodb_id, null::geometry as the_geom_webmercator',
|
|
|
|
cartocss: '#layer { marker-fill:blue; }',
|
|
|
|
cartocss_version: '2.3.0'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
},
|
|
|
|
expectedBody = { template_id: expectedTemplateId };
|
|
|
|
|
2015-03-30 23:51:17 +08:00
|
|
|
var varnishHttpUrl = [
|
2015-07-05 02:41:22 +08:00
|
|
|
'http://', serverOptions.varnish_host, ':', serverOptions.varnish_http_port
|
2015-03-30 23:51:17 +08:00
|
|
|
].join('');
|
|
|
|
|
|
|
|
var cacheEntryKey = new NamedMapsCacheEntry(templateOwner, templateName).key();
|
|
|
|
var invalidationMatchHeader = '\\b' + cacheEntryKey + '\\b';
|
2015-04-27 23:43:46 +08:00
|
|
|
var fastlyPurgePath = '/service/' + FAKE_FASTLY_SERVICE_ID + '/purge/' + encodeURIComponent(cacheEntryKey);
|
2015-03-30 23:51:17 +08:00
|
|
|
|
|
|
|
var nock = require('nock');
|
|
|
|
nock.enableNetConnect(/(127.0.0.1:5555|cartocdn.com)/);
|
|
|
|
|
|
|
|
after(function(done) {
|
|
|
|
serverOptions.varnish_purge_enabled = false;
|
2015-07-05 02:41:22 +08:00
|
|
|
serverOptions.varnish_host = varnishHost;
|
|
|
|
serverOptions.varnish_purge_enabled = varnishPurgeEnabled;
|
2015-03-30 23:51:17 +08:00
|
|
|
|
2015-07-05 02:41:22 +08:00
|
|
|
serverOptions.fastly = fastlyConfig;
|
2015-04-27 23:43:46 +08:00
|
|
|
|
2015-03-30 23:51:17 +08:00
|
|
|
nock.restore();
|
|
|
|
done();
|
|
|
|
});
|
2015-01-26 22:02:28 +08:00
|
|
|
|
2015-01-30 23:50:06 +08:00
|
|
|
function createTemplate(callback) {
|
2015-01-26 22:02:28 +08:00
|
|
|
var postTemplateRequest = {
|
2015-03-23 22:54:45 +08:00
|
|
|
url: '/api/v1/map/named?api_key=1234',
|
2015-01-26 22:02:28 +08:00
|
|
|
method: 'POST',
|
|
|
|
headers: {
|
|
|
|
host: templateOwner,
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
},
|
|
|
|
data: JSON.stringify(template)
|
|
|
|
};
|
|
|
|
|
2015-03-24 17:38:14 +08:00
|
|
|
step(
|
2015-01-26 22:02:28 +08:00
|
|
|
function postTemplate() {
|
|
|
|
var next = this;
|
|
|
|
assert.response(server,
|
|
|
|
postTemplateRequest,
|
|
|
|
{
|
|
|
|
status: 200
|
|
|
|
},
|
|
|
|
function(res) {
|
|
|
|
next(null, res);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
},
|
|
|
|
function rePostTemplate(err, res) {
|
|
|
|
if (err) {
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
var parsedBody = JSON.parse(res.body);
|
|
|
|
assert.deepEqual(parsedBody, expectedBody);
|
|
|
|
return true;
|
|
|
|
},
|
|
|
|
function finish(err) {
|
2015-01-30 23:50:06 +08:00
|
|
|
callback(err);
|
2015-01-26 22:02:28 +08:00
|
|
|
}
|
|
|
|
);
|
2015-01-30 23:50:06 +08:00
|
|
|
}
|
2015-01-26 22:02:28 +08:00
|
|
|
|
2015-03-30 23:51:17 +08:00
|
|
|
it("invalidates surrogate keys on template update", function(done) {
|
|
|
|
|
|
|
|
var scope = nock(varnishHttpUrl)
|
|
|
|
.intercept('/key', 'PURGE')
|
|
|
|
.matchHeader('Invalidation-Match', invalidationMatchHeader)
|
|
|
|
.reply(204, '');
|
2015-01-26 22:02:28 +08:00
|
|
|
|
2015-04-27 23:43:46 +08:00
|
|
|
var fastlyScope = nock(FastlyPurge.FASTLY_API_ENDPOINT)
|
|
|
|
.post(fastlyPurgePath)
|
|
|
|
.matchHeader('Fastly-Key', FAKE_FASTLY_API_KEY)
|
|
|
|
.matchHeader('Fastly-Soft-Purge', 1)
|
|
|
|
.matchHeader('Accept', 'application/json')
|
|
|
|
.reply(200, {
|
|
|
|
status:'ok'
|
|
|
|
});
|
|
|
|
|
2015-03-24 17:38:14 +08:00
|
|
|
step(
|
2015-01-30 23:50:06 +08:00
|
|
|
function createTemplateToUpdate() {
|
|
|
|
createTemplate(this);
|
|
|
|
},
|
|
|
|
function putValidTemplate(err) {
|
|
|
|
if (err) {
|
|
|
|
throw err;
|
|
|
|
}
|
2015-01-26 22:02:28 +08:00
|
|
|
var updateTemplateRequest = {
|
2015-03-23 22:54:45 +08:00
|
|
|
url: '/api/v1/map/named/' + expectedTemplateId + '/?api_key=1234',
|
2015-01-26 22:02:28 +08:00
|
|
|
method: 'PUT',
|
|
|
|
headers: {
|
|
|
|
host: templateOwner,
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
},
|
|
|
|
data: JSON.stringify(template)
|
|
|
|
};
|
|
|
|
var next = this;
|
|
|
|
assert.response(server,
|
|
|
|
updateTemplateRequest,
|
|
|
|
{
|
|
|
|
status: 200
|
|
|
|
},
|
|
|
|
function(res) {
|
2015-09-16 19:17:03 +08:00
|
|
|
setTimeout(function() {
|
|
|
|
next(null, res);
|
|
|
|
}, 50);
|
2015-01-26 22:02:28 +08:00
|
|
|
}
|
|
|
|
);
|
|
|
|
},
|
|
|
|
function checkValidUpdate(err, res) {
|
|
|
|
if (err) {
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
var parsedBody = JSON.parse(res.body);
|
|
|
|
assert.deepEqual(parsedBody, expectedBody);
|
|
|
|
|
2015-03-30 23:51:17 +08:00
|
|
|
assert.equal(scope.pendingMocks().length, 0);
|
2015-04-27 23:43:46 +08:00
|
|
|
assert.equal(fastlyScope.pendingMocks().length, 0);
|
2015-01-26 22:02:28 +08:00
|
|
|
|
|
|
|
return null;
|
|
|
|
},
|
|
|
|
function finish(err) {
|
|
|
|
if ( err ) {
|
|
|
|
return done(err);
|
|
|
|
}
|
|
|
|
redisClient.keys("map_*|localhost", function(err, keys) {
|
|
|
|
if ( err ) {
|
|
|
|
return done(err);
|
|
|
|
}
|
|
|
|
redisClient.del(keys, function(err) {
|
|
|
|
return done(err);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
2015-03-30 23:51:17 +08:00
|
|
|
it("invalidates surrogate on template deletion", function(done) {
|
2015-01-26 22:02:28 +08:00
|
|
|
|
2015-03-30 23:51:17 +08:00
|
|
|
var scope = nock(varnishHttpUrl)
|
|
|
|
.intercept('/key', 'PURGE')
|
|
|
|
.matchHeader('Invalidation-Match', invalidationMatchHeader)
|
|
|
|
.reply(204, '');
|
2015-01-26 22:02:28 +08:00
|
|
|
|
2015-04-27 23:43:46 +08:00
|
|
|
var fastlyScope = nock(FastlyPurge.FASTLY_API_ENDPOINT)
|
|
|
|
.post(fastlyPurgePath)
|
|
|
|
.matchHeader('Fastly-Key', FAKE_FASTLY_API_KEY)
|
|
|
|
.matchHeader('Fastly-Soft-Purge', 1)
|
|
|
|
.matchHeader('Accept', 'application/json')
|
|
|
|
.reply(200, {
|
|
|
|
status:'ok'
|
|
|
|
});
|
|
|
|
|
2015-03-24 17:38:14 +08:00
|
|
|
step(
|
2015-01-30 23:50:06 +08:00
|
|
|
function createTemplateToDelete() {
|
|
|
|
createTemplate(this);
|
|
|
|
},
|
|
|
|
function deleteValidTemplate(err) {
|
|
|
|
if (err) {
|
|
|
|
throw err;
|
|
|
|
}
|
2015-01-26 22:02:28 +08:00
|
|
|
var deleteTemplateRequest = {
|
2015-03-23 22:54:45 +08:00
|
|
|
url: '/api/v1/map/named/' + expectedTemplateId + '/?api_key=1234',
|
2015-01-26 22:02:28 +08:00
|
|
|
method: 'DELETE',
|
|
|
|
headers: {
|
|
|
|
host: templateOwner,
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
}
|
|
|
|
};
|
|
|
|
var next = this;
|
|
|
|
assert.response(server,
|
|
|
|
deleteTemplateRequest,
|
|
|
|
{
|
|
|
|
status: 204
|
|
|
|
},
|
|
|
|
function(res) {
|
2015-09-16 19:17:03 +08:00
|
|
|
setTimeout(function() {
|
|
|
|
next(null, res);
|
|
|
|
}, 50);
|
2015-01-26 22:02:28 +08:00
|
|
|
}
|
|
|
|
);
|
|
|
|
},
|
|
|
|
function checkValidUpdate(err) {
|
|
|
|
if (err) {
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
|
2015-03-30 23:51:17 +08:00
|
|
|
assert.equal(scope.pendingMocks().length, 0);
|
2015-04-27 23:43:46 +08:00
|
|
|
assert.equal(fastlyScope.pendingMocks().length, 0);
|
2015-01-26 22:02:28 +08:00
|
|
|
|
|
|
|
return null;
|
|
|
|
},
|
|
|
|
function finish(err) {
|
|
|
|
done(err);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
2015-03-30 23:51:17 +08:00
|
|
|
it("should update template even if surrogate key invalidation fails", function(done) {
|
|
|
|
|
|
|
|
var scope = nock(varnishHttpUrl)
|
|
|
|
.intercept('/key', 'PURGE')
|
|
|
|
.matchHeader('Invalidation-Match', invalidationMatchHeader)
|
|
|
|
.reply(503, '');
|
|
|
|
|
2015-09-16 19:17:03 +08:00
|
|
|
var fastlyScope = nock(FastlyPurge.FASTLY_API_ENDPOINT)
|
|
|
|
.post(fastlyPurgePath)
|
|
|
|
.matchHeader('Fastly-Key', FAKE_FASTLY_API_KEY)
|
|
|
|
.matchHeader('Fastly-Soft-Purge', 1)
|
|
|
|
.matchHeader('Accept', 'application/json')
|
|
|
|
.reply(200, {
|
|
|
|
status:'ok'
|
|
|
|
});
|
|
|
|
|
2015-03-30 23:51:17 +08:00
|
|
|
step(
|
|
|
|
function createTemplateToUpdate() {
|
|
|
|
createTemplate(this);
|
|
|
|
},
|
|
|
|
function putValidTemplate(err) {
|
|
|
|
if (err) {
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
var updateTemplateRequest = {
|
|
|
|
url: '/api/v1/map/named/' + expectedTemplateId + '/?api_key=1234',
|
|
|
|
method: 'PUT',
|
|
|
|
headers: {
|
|
|
|
host: templateOwner,
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
},
|
|
|
|
data: JSON.stringify(template)
|
|
|
|
};
|
|
|
|
var next = this;
|
|
|
|
assert.response(server,
|
|
|
|
updateTemplateRequest,
|
|
|
|
{
|
|
|
|
status: 200
|
|
|
|
},
|
|
|
|
function(res) {
|
2015-09-16 19:17:03 +08:00
|
|
|
setTimeout(function() {
|
|
|
|
next(null, res);
|
|
|
|
}, 50);
|
2015-03-30 23:51:17 +08:00
|
|
|
}
|
|
|
|
);
|
|
|
|
},
|
|
|
|
function checkValidUpdate(err, res) {
|
|
|
|
if (err) {
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
var parsedBody = JSON.parse(res.body);
|
|
|
|
assert.deepEqual(parsedBody, expectedBody);
|
|
|
|
|
|
|
|
assert.equal(scope.pendingMocks().length, 0);
|
2015-09-16 19:17:03 +08:00
|
|
|
assert.equal(fastlyScope.pendingMocks().length, 0);
|
2015-03-30 23:51:17 +08:00
|
|
|
|
|
|
|
return null;
|
|
|
|
},
|
|
|
|
function finish(err) {
|
|
|
|
if ( err ) {
|
|
|
|
return done(err);
|
|
|
|
}
|
|
|
|
redisClient.keys("map_*|localhost", function(err, keys) {
|
|
|
|
if ( err ) {
|
|
|
|
return done(err);
|
|
|
|
}
|
|
|
|
redisClient.del(keys, function(err) {
|
|
|
|
return done(err);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
);
|
2015-01-26 22:02:28 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
});
|