Skip to content

Commit

Permalink
Tests and log cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
philrenaud committed Jul 8, 2024
1 parent 8a4d302 commit ffa45c2
Show file tree
Hide file tree
Showing 11 changed files with 173 additions and 85 deletions.
3 changes: 3 additions & 0 deletions .changelog/23506.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:improvement
ui: Allow users to create Global ACL tokens from the Administration UI
```
9 changes: 0 additions & 9 deletions ui/app/adapters/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,24 +58,15 @@ export default class ApplicationAdapter extends RESTAdapter {
}

ajaxOptions(url, verb, options = {}) {
// console.log('+++ is ajaxOptions for', url, ' ever hit?', this.get('system.shouldIncludeRegion'));
options.data || (options.data = {});
if (options.regionOverride || this.get('system.shouldIncludeRegion')) {
// Region should only ever be a query param. The default ajaxOptions
// behavior is to include data attributes in the requestBody for PUT
// and POST requests. This works around that.
const region = options.regionOverride || this.get('system.activeRegion');
console.log(
'region ultimately will be',
region,
'override?',
options.regionOverride
);
// console.log('ajaxOptions, system activeRegion check?', region)
if (region) {
url = associateRegion(url, region);
}
console.log('so url then', url);
}
return super.ajaxOptions(url, verb, options);
}
Expand Down
8 changes: 0 additions & 8 deletions ui/app/adapters/token.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,9 @@ export default class TokenAdapter extends ApplicationAdapter {

createRecord(_store, type, snapshot) {
let data = this.serialize(snapshot);
console.log(
'token createRecord, what is its region',
data.region,
data.global,
data,
snapshot
);
if (snapshot.adapterOptions?.region) {
// ajaxOptions will try to append a particular region here.
// we want instead fo overwrite it with the token's region.
// this.region = data.region;
return this.ajax(`${this.buildURL()}/token`, 'POST', {
data,
regionOverride: snapshot.adapterOptions.region,
Expand Down
2 changes: 0 additions & 2 deletions ui/app/components/region-switcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ export default class RegionSwitcher extends Component {
}

async gotoRegion(region) {
// Reset token
// this.token.reset();
// Note: redundant but as long as we're using PowerSelect, the implicit set('activeRegion')
// is not something we can await, so we do it explicitly here.
this.system.set('activeRegion', region);
Expand Down
10 changes: 4 additions & 6 deletions ui/app/components/token-editor.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -95,19 +95,17 @@
</div>
{{/unless}}

{{!-- Global or Local --}}
{{#if @token.isNew}}
{{!-- {{log "SYSTEM REGION INFO" this.system.regions this.system.defaultRegion this.system.activeRegion this.system}} --}}
{{#if this.system.regions.length}}
{{#if this.system.shouldShowRegions}}
<Hds::Form::Radio::Group data-test-global-token-group @layout="horizontal" @name="regional-or-global" {{on "change" this.updateTokenLocality}} as |G|>
<G.Legend>Token Region ((({{this.tokenRegion}})))</G.Legend>
{{!-- <G.HelperText>See <Hds::Link::Inline @href="https://developer.hashicorp.com/nomad/tutorials/access-control/access-control-tokens#token-types">Token types documentation</Hds::Link::Inline> for more information.</G.HelperText> --}}
<G.Legend>Token Region</G.Legend>
<G.HelperText>See <Hds::Link::Inline @href="https://developer.hashicorp.com/nomad/tutorials/access-control/access-control-tokens#token-replication-settings">ACL token fundamentals: Token replication settings</Hds::Link::Inline> for more information.</G.HelperText>
<G.RadioField
@id={{this.system.activeRegion}}
checked={{eq this.tokenRegion this.system.activeRegion}}
data-test-locality="active-region"
as |F|>
<F.Label>{{this.system.activeRegion}}</F.Label>
<F.Label data-test-active-region-label>{{this.system.activeRegion}}</F.Label>
</G.RadioField>
{{#if this.system.defaultRegion.region}}
{{!-- template-lint-disable simple-unless --}}
Expand Down
20 changes: 0 additions & 20 deletions ui/app/components/token-editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,16 +84,7 @@ export default class TokenEditorComponent extends Component {
}

@action updateTokenLocality(event) {
console.log('udpateTokenLocality', event.target.id);
this.tokenRegion = event.target.id;
// if (this.tokenRegion === 'global') {
// this.activeToken.global = true;
// this.activeToken.region = '';
// } else {
// this.activeToken.global = false;
// // do I need to do anything else here or just wait until save??
// this.activeToken.region = this.tokenRegion;
// }
}

@action async save() {
Expand All @@ -113,17 +104,8 @@ export default class TokenEditorComponent extends Component {

if (this.tokenRegion === 'global') {
this.activeToken.global = true;
// set to authoritative region
// this.activeToken.region = this.system.get('defaultRegion.region');
console.log(
'and thus',
this.activeToken.region,
this.system.get('defaultRegion.region')
);
} else {
console.log('setting region to', this.tokenRegion);
this.activeToken.global = false;
// this.activeToken.region = this.tokenRegion;
}

// Sets to "never" for auto-selecting the radio button;
Expand All @@ -138,8 +120,6 @@ export default class TokenEditorComponent extends Component {
? this.system.get('defaultRegion.region')
: this.tokenRegion;

console.log('about to save and', adapterRegion);

await this.activeToken.save({
adapterOptions: adapterRegion ? { region: adapterRegion } : {},
});
Expand Down
2 changes: 0 additions & 2 deletions ui/app/controllers/clients/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ export default class IndexController extends Controller.extend(
@controller('clients') clientsController;

@alias('model.nodes') nodes;
// TODO: needed?
// @alias('model.agents') agents;

queryParams = [
{
Expand Down
2 changes: 0 additions & 2 deletions ui/app/routes/clients.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ export default class ClientsRoute extends Route.extend(WithForbiddenState) {
model() {
return RSVP.hash({
nodes: this.store.findAll('node'),
// TODO: needed?
// agents: this.store.findAll('agent'),
nodePools: this.store.findAll('node-pool'),
}).catch(notifyForbidden(this));
}
Expand Down
7 changes: 3 additions & 4 deletions ui/mirage/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -730,9 +730,8 @@ export default function () {
});

this.post('/acl/token', function (schema, request) {
const { Name, Policies, Type, ExpirationTTL, ExpirationTime } = JSON.parse(
request.requestBody
);
const { Name, Policies, Type, ExpirationTTL, ExpirationTime, Global } =
JSON.parse(request.requestBody);

function parseDuration(duration) {
const [_, value, unit] = duration.match(/(\d+)(\w)/);
Expand All @@ -758,6 +757,7 @@ export default function () {
type: Type,
id: faker.random.uuid(),
expirationTime,
global: Global,
createTime: new Date().toISOString(),
});
});
Expand Down Expand Up @@ -1045,7 +1045,6 @@ export default function () {
});

this.get('/regions', function ({ regions }) {
console.log('get regions and', regions.all());
return this.serialize(regions.all());
});

Expand Down
10 changes: 0 additions & 10 deletions ui/tests/acceptance/regions-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,16 +158,6 @@ module('Acceptance | regions (many)', function (hooks) {
);
});

test('switching regions on deep pages redirects to the application root', async function (assert) {
const newRegion = server.db.regions[1].id;

await Allocation.visit({ id: server.db.allocations[0].id });

await selectChoose('[data-test-region-switcher-parent]', newRegion);

assert.ok(currentURL().includes('/jobs?'), 'Back at the jobs page');
});

test('navigating directly to a page with the region query param sets the application to that region', async function (assert) {
const allocation = server.db.allocations[0];
const region = server.db.regions[1].id;
Expand Down
185 changes: 163 additions & 22 deletions ui/tests/acceptance/token-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1144,28 +1144,6 @@ module('Acceptance | tokens', function (hooks) {
await Administration.visitTokens();
assert.dom('[data-test-token-name="Mud-Token"]').exists({ count: 1 });
});
test('When no regions are present, Tokens are by default regional', async function (assert) {
await visit('/administration/tokens/new');
assert.dom('[data-test-token-global]').doesNotExist();

await fillIn('[data-test-token-name-input]', 'Capt. Steven Hiller');
await click('[data-test-token-save]');
assert.dom('.flash-message.alert-success').exists();
const token = server.db.tokens.findBy(
(t) => t.name === 'Capt. Steven Hiller'
);
assert.false(token.global);
});

test('When regions are present, Tokens are by default regional, but can be made global', async function (assert) {
server.create('region', { id: 'America' });
server.create('region', { id: 'washington-dc' });
console.log('regions created');
// TODO: the mirage call to /regions happens before they are created here. Set them up in a module.beforeEach.
await visit('/administration/tokens/new');
assert.dom('[data-test-token-global]').exists();
// await this.pauseTest();
});

test('Token policies and roles can be edited', async function (assert) {
const token = server.db.tokens.findBy((t) => t.id === 'cl4y-t0k3n');
Expand Down Expand Up @@ -1324,5 +1302,168 @@ module('Acceptance | tokens', function (hooks) {
.dom(expiringTokenExpirationCell)
.hasText('in 2 hours', 'Expiration time is relativized and rounded');
});

test('When no regions are present, Tokens are by default regional', async function (assert) {
await visit('/administration/tokens/new');
assert.dom('[data-test-global-token-group]').doesNotExist();

await fillIn('[data-test-token-name-input]', 'Capt. Steven Hiller');
await click('[data-test-token-save]');
assert.dom('.flash-message.alert-success').exists();
const token = server.db.tokens.findBy(
(t) => t.name === 'Capt. Steven Hiller'
);
assert.false(token.global);
});
});
});

module('Tokens and Regions', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);

hooks.beforeEach(function () {
window.localStorage.clear();
window.sessionStorage.clear();
faker.seed(1);

server.create('region', { id: 'america' });
server.create('region', { id: 'washington-dc' });
server.create('region', { id: 'new-york' });
server.create('region', { id: 'alien-ship' });

server.create('agent');
server.create('node-pool');
server.create('namespace');
node = server.create('node');
job = server.create('job');
managementToken = server.create('token');

window.localStorage.nomadTokenSecret = managementToken.secretId;
});
test('When regions are present, Tokens are by default regional, but can be made global', async function (assert) {
await visit('/administration/tokens/new');
assert.dom('[data-test-global-token-group]').exists();
});

test('A global token can be created, and gets saved in the authoritative region', async function (assert) {
await visit('/administration/tokens/new');
assert
.dom('[data-test-active-region-label]')
.hasText('america', 'america is the default selected region');
assert
.dom('[data-test-locality]')
.exists(
{ count: 2 },
'When in the authoritative/default region, only it and global are region options'
);

// change region from dropdown
await selectChoose('[data-test-region-switcher-parent]', 'washington-dc');

assert
.dom('[data-test-active-region-label]')
.hasText('washington-dc', 'washington-dc is the selected region');
assert.dom('[data-test-locality="active-region"]').isChecked();

assert
.dom('[data-test-locality]')
.exists(
{ count: 3 },
'When in a region other than the authoritative one, the authoritative group becomes an third option in addition to current region and global'
);

await fillIn('[data-test-token-name-input]', 'Thomas J. Whitmore');
await click('[data-test-locality="global"]');
assert.dom('[data-test-locality="global"]').isChecked();

await click('[data-test-token-type="management"]');
await click('[data-test-token-save]');

let globalToken = server.db.tokens.findBy(
(t) => t.name === 'Thomas J. Whitmore'
);
assert.ok(globalToken.global, 'Token has Global set to true');
assert.dom('.flash-message.alert-success').exists();
let tokenRequest = server.pretender.handledRequests.find((req) => {
return req.url.includes('acl/token') && req.method === 'POST';
});
assert.equal(
tokenRequest.queryParams.region,
'america',
'Global token is saved in the authoritative region, regardless of active UI region'
);
await percySnapshot(assert);
});

test('A token can be created in a non-authoritative region', async function (assert) {
await visit('/administration/tokens/new');
assert
.dom('[data-test-active-region-label]')
.hasText('america', 'america is the default selected region');
assert
.dom('[data-test-locality]')
.exists(
{ count: 2 },
'When in the authoritative/default region, only it and global are region options'
);

// change region from dropdown
await selectChoose('[data-test-region-switcher-parent]', 'alien-ship');

assert
.dom('[data-test-active-region-label]')
.hasText('alien-ship', 'alien-ship is the selected region');
assert.dom('[data-test-locality="active-region"]').isChecked();

await fillIn('[data-test-token-name-input]', 'David Levinson');
await click('[data-test-token-type="management"]');
await click('[data-test-token-save]');
assert.dom('.flash-message.alert-success').exists();
let token = server.db.tokens.findBy((t) => t.name === 'David Levinson');

assert.notOk(token.global, 'Token is not global');
const tokenRequest = server.pretender.handledRequests.find((req) => {
return req.url.includes('acl/token') && req.method === 'POST';
});

assert.equal(
tokenRequest.queryParams.region,
'alien-ship',
'Token is saved in the selected region'
);
});

test('A non-global token can be created in the authoritative region', async function (assert) {
await visit('/administration/tokens/new');

// change region from dropdown
await selectChoose('[data-test-region-switcher-parent]', 'new-york');

assert
.dom('[data-test-active-region-label]')
.hasText('new-york', 'new-york is the selected region');
assert.dom('[data-test-locality="active-region"]').isChecked();

await click('[data-test-locality="default-region"]');
assert.dom('[data-test-locality="default-region"]').isChecked();

await fillIn('[data-test-token-name-input]', 'Russell Casse');
await click('[data-test-token-type="management"]');
// await this.pauseTest();

await click('[data-test-token-save]');
assert.dom('.flash-message.alert-success').exists();
let token = server.db.tokens.findBy((t) => t.name === 'Russell Casse');
assert.notOk(token.global, 'Token is not global');
const tokenRequest = server.pretender.handledRequests.find((req) => {
return req.url.includes('acl/token') && req.method === 'POST';
});

assert.equal(
tokenRequest.queryParams.region,
'america',
'Token is saved in the authoritative region'
);
});
});

0 comments on commit ffa45c2

Please sign in to comment.