github.com/hernad/nomad@v1.6.112/ui/tests/unit/abilities/variable-test.js (about)

     1  /**
     2   * Copyright (c) HashiCorp, Inc.
     3   * SPDX-License-Identifier: MPL-2.0
     4   */
     5  
     6  /* eslint-disable ember/avoid-leaking-state-in-ember-objects */
     7  import { module, test } from 'qunit';
     8  import { setupTest } from 'ember-qunit';
     9  import Service from '@ember/service';
    10  import setupAbility from 'nomad-ui/tests/helpers/setup-ability';
    11  
    12  module('Unit | Ability | variable', function (hooks) {
    13    setupTest(hooks);
    14    setupAbility('variable')(hooks);
    15    hooks.beforeEach(function () {
    16      const mockSystem = Service.extend({
    17        features: [],
    18      });
    19  
    20      this.owner.register('service:system', mockSystem);
    21    });
    22  
    23    module('#list', function () {
    24      test('it does not permit listing variables by default', function (assert) {
    25        const mockToken = Service.extend({
    26          aclEnabled: true,
    27        });
    28  
    29        this.owner.register('service:token', mockToken);
    30  
    31        assert.notOk(this.ability.canList);
    32      });
    33  
    34      test('it does not permit listing variables when token type is client', function (assert) {
    35        const mockToken = Service.extend({
    36          aclEnabled: true,
    37          selfToken: { type: 'client' },
    38        });
    39  
    40        this.owner.register('service:token', mockToken);
    41  
    42        assert.notOk(this.ability.canList);
    43      });
    44  
    45      test('it permits listing variables when token type is management', function (assert) {
    46        const mockToken = Service.extend({
    47          aclEnabled: true,
    48          selfToken: { type: 'management' },
    49        });
    50  
    51        this.owner.register('service:token', mockToken);
    52  
    53        assert.ok(this.ability.canList);
    54      });
    55  
    56      test('it permits listing variables when token has Variables with list capabilities in its rules', function (assert) {
    57        const mockToken = Service.extend({
    58          aclEnabled: true,
    59          selfToken: { type: 'client' },
    60          selfTokenPolicies: [
    61            {
    62              rulesJSON: {
    63                Namespaces: [
    64                  {
    65                    Name: 'default',
    66                    Capabilities: [],
    67                    Variables: {
    68                      Paths: [{ Capabilities: ['list'], PathSpec: '*' }],
    69                    },
    70                  },
    71                ],
    72              },
    73            },
    74          ],
    75        });
    76  
    77        this.owner.register('service:token', mockToken);
    78  
    79        assert.ok(this.ability.canList);
    80      });
    81  
    82      test('it does not permit listing variables when token has Variables alone in its rules', function (assert) {
    83        const mockToken = Service.extend({
    84          aclEnabled: true,
    85          selfToken: { type: 'client' },
    86          selfTokenPolicies: [
    87            {
    88              rulesJSON: {
    89                Namespaces: [
    90                  {
    91                    Name: 'default',
    92                    Capabilities: [],
    93                    Variables: {},
    94                  },
    95                ],
    96              },
    97            },
    98          ],
    99        });
   100  
   101        this.owner.register('service:token', mockToken);
   102  
   103        assert.notOk(this.ability.canList);
   104      });
   105  
   106      test('it does not permit listing variables when token has a null Variables block', function (assert) {
   107        const mockToken = Service.extend({
   108          aclEnabled: true,
   109          selfToken: { type: 'client' },
   110          selfTokenPolicies: [
   111            {
   112              rulesJSON: {
   113                Namespaces: [
   114                  {
   115                    Name: 'default',
   116                    Capabilities: [],
   117                    Variables: null,
   118                  },
   119                ],
   120              },
   121            },
   122          ],
   123        });
   124  
   125        this.owner.register('service:token', mockToken);
   126  
   127        assert.notOk(this.ability.canList);
   128      });
   129  
   130      test('it does not permit listing variables when token has a Variables block where paths are without capabilities', function (assert) {
   131        const mockToken = Service.extend({
   132          aclEnabled: true,
   133          selfToken: { type: 'client' },
   134          selfTokenPolicies: [
   135            {
   136              rulesJSON: {
   137                Namespaces: [
   138                  {
   139                    Name: 'default',
   140                    Capabilities: [],
   141                    Variables: {
   142                      Paths: [
   143                        { Capabilities: [], PathSpec: '*' },
   144                        { Capabilities: [], PathSpec: 'foo' },
   145                        { Capabilities: [], PathSpec: 'foo/bar' },
   146                      ],
   147                    },
   148                  },
   149                ],
   150              },
   151            },
   152          ],
   153        });
   154  
   155        this.owner.register('service:token', mockToken);
   156  
   157        assert.notOk(this.ability.canList);
   158      });
   159  
   160      test('it does not permit listing variables when token has no Variables block', function (assert) {
   161        const mockToken = Service.extend({
   162          aclEnabled: true,
   163          selfToken: { type: 'client' },
   164          selfTokenPolicies: [
   165            {
   166              rulesJSON: {
   167                Namespaces: [
   168                  {
   169                    Name: 'default',
   170                    Capabilities: [],
   171                  },
   172                ],
   173              },
   174            },
   175          ],
   176        });
   177  
   178        this.owner.register('service:token', mockToken);
   179  
   180        assert.notOk(this.ability.canList);
   181      });
   182  
   183      test('it permits listing variables when token multiple namespaces, only one of which having a Variables block', function (assert) {
   184        const mockToken = Service.extend({
   185          aclEnabled: true,
   186          selfToken: { type: 'client' },
   187          selfTokenPolicies: [
   188            {
   189              rulesJSON: {
   190                Namespaces: [
   191                  {
   192                    Name: 'default',
   193                    Capabilities: [],
   194                    Variables: null,
   195                  },
   196                  {
   197                    Name: 'nonsense',
   198                    Capabilities: [],
   199                    Variables: {
   200                      Paths: [{ Capabilities: [], PathSpec: '*' }],
   201                    },
   202                  },
   203                  {
   204                    Name: 'shenanigans',
   205                    Capabilities: [],
   206                    Variables: {
   207                      Paths: [
   208                        { Capabilities: ['list'], PathSpec: 'foo/bar/baz' },
   209                      ],
   210                    },
   211                  },
   212                ],
   213              },
   214            },
   215          ],
   216        });
   217  
   218        this.owner.register('service:token', mockToken);
   219  
   220        assert.ok(this.ability.canList);
   221      });
   222    });
   223  
   224    module('#create', function () {
   225      test('it does not permit creating variables by default', function (assert) {
   226        const mockToken = Service.extend({
   227          aclEnabled: true,
   228        });
   229  
   230        this.owner.register('service:token', mockToken);
   231  
   232        assert.notOk(this.ability.canWrite);
   233      });
   234  
   235      test('it permits creating variables when token type is management', function (assert) {
   236        const mockToken = Service.extend({
   237          aclEnabled: true,
   238          selfToken: { type: 'management' },
   239        });
   240  
   241        this.owner.register('service:token', mockToken);
   242  
   243        assert.ok(this.ability.canWrite);
   244      });
   245  
   246      test('it permits creating variables when acl is disabled', function (assert) {
   247        const mockToken = Service.extend({
   248          aclEnabled: false,
   249          selfToken: { type: 'client' },
   250        });
   251  
   252        this.owner.register('service:token', mockToken);
   253  
   254        assert.ok(this.ability.canWrite);
   255      });
   256  
   257      test('it permits creating variables when token has Variables with write capabilities in its rules', function (assert) {
   258        const mockToken = Service.extend({
   259          aclEnabled: true,
   260          selfToken: { type: 'client' },
   261          selfTokenPolicies: [
   262            {
   263              rulesJSON: {
   264                Namespaces: [
   265                  {
   266                    Name: 'default',
   267                    Capabilities: [],
   268                    Variables: {
   269                      Paths: [{ Capabilities: ['write'], PathSpec: '*' }],
   270                    },
   271                  },
   272                ],
   273              },
   274            },
   275          ],
   276        });
   277  
   278        this.owner.register('service:token', mockToken);
   279  
   280        assert.ok(this.ability.canWrite);
   281      });
   282  
   283      test('it handles namespace matching', function (assert) {
   284        const mockToken = Service.extend({
   285          aclEnabled: true,
   286          selfToken: { type: 'client' },
   287          selfTokenPolicies: [
   288            {
   289              rulesJSON: {
   290                Namespaces: [
   291                  {
   292                    Name: 'default',
   293                    Capabilities: [],
   294                    Variables: {
   295                      Paths: [{ Capabilities: ['list'], PathSpec: 'foo/bar' }],
   296                    },
   297                  },
   298                  {
   299                    Name: 'pablo',
   300                    Capabilities: [],
   301                    Variables: {
   302                      Paths: [{ Capabilities: ['write'], PathSpec: 'foo/bar' }],
   303                    },
   304                  },
   305                ],
   306              },
   307            },
   308          ],
   309        });
   310  
   311        this.owner.register('service:token', mockToken);
   312        this.ability.path = 'foo/bar';
   313        this.ability.namespace = 'pablo';
   314  
   315        assert.ok(this.ability.canWrite);
   316      });
   317    });
   318  
   319    module('#destroy', function () {
   320      test('it does not permit destroying variables by default', function (assert) {
   321        const mockToken = Service.extend({
   322          aclEnabled: true,
   323        });
   324  
   325        this.owner.register('service:token', mockToken);
   326  
   327        assert.notOk(this.ability.canDestroy);
   328      });
   329  
   330      test('it permits destroying variables when token type is management', function (assert) {
   331        const mockToken = Service.extend({
   332          aclEnabled: true,
   333          selfToken: { type: 'management' },
   334        });
   335  
   336        this.owner.register('service:token', mockToken);
   337  
   338        assert.ok(this.ability.canDestroy);
   339      });
   340  
   341      test('it permits destroying variables when acl is disabled', function (assert) {
   342        const mockToken = Service.extend({
   343          aclEnabled: false,
   344          selfToken: { type: 'client' },
   345        });
   346  
   347        this.owner.register('service:token', mockToken);
   348  
   349        assert.ok(this.ability.canDestroy);
   350      });
   351  
   352      test('it permits destroying variables when token has Variables with write capabilities in its rules', function (assert) {
   353        const mockToken = Service.extend({
   354          aclEnabled: true,
   355          selfToken: { type: 'client' },
   356          selfTokenPolicies: [
   357            {
   358              rulesJSON: {
   359                Namespaces: [
   360                  {
   361                    Name: 'default',
   362                    Capabilities: [],
   363                    Variables: {
   364                      Paths: [{ Capabilities: ['destroy'], PathSpec: '*' }],
   365                    },
   366                  },
   367                ],
   368              },
   369            },
   370          ],
   371        });
   372  
   373        this.owner.register('service:token', mockToken);
   374  
   375        assert.ok(this.ability.canDestroy);
   376      });
   377  
   378      test('it handles namespace matching', function (assert) {
   379        const mockToken = Service.extend({
   380          aclEnabled: true,
   381          selfToken: { type: 'client' },
   382          selfTokenPolicies: [
   383            {
   384              rulesJSON: {
   385                Namespaces: [
   386                  {
   387                    Name: 'default',
   388                    Capabilities: [],
   389                    Variables: {
   390                      Paths: [{ Capabilities: ['list'], PathSpec: 'foo/bar' }],
   391                    },
   392                  },
   393                  {
   394                    Name: 'pablo',
   395                    Capabilities: [],
   396                    Variables: {
   397                      Paths: [{ Capabilities: ['destroy'], PathSpec: 'foo/bar' }],
   398                    },
   399                  },
   400                ],
   401              },
   402            },
   403          ],
   404        });
   405  
   406        this.owner.register('service:token', mockToken);
   407        this.ability.path = 'foo/bar';
   408        this.ability.namespace = 'pablo';
   409  
   410        assert.ok(this.ability.canDestroy);
   411      });
   412    });
   413  
   414    module('#read', function () {
   415      test('it does not permit reading variables by default', function (assert) {
   416        const mockToken = Service.extend({
   417          aclEnabled: true,
   418        });
   419  
   420        this.owner.register('service:token', mockToken);
   421  
   422        assert.notOk(this.ability.canRead);
   423      });
   424  
   425      test('it permits reading variables when token type is management', function (assert) {
   426        const mockToken = Service.extend({
   427          aclEnabled: true,
   428          selfToken: { type: 'management' },
   429        });
   430  
   431        this.owner.register('service:token', mockToken);
   432  
   433        assert.ok(this.ability.canRead);
   434      });
   435  
   436      test('it permits reading variables when acl is disabled', function (assert) {
   437        const mockToken = Service.extend({
   438          aclEnabled: false,
   439          selfToken: { type: 'client' },
   440        });
   441  
   442        this.owner.register('service:token', mockToken);
   443  
   444        assert.ok(this.ability.canRead);
   445      });
   446  
   447      test('it permits reading variables when token has Variables with read capabilities in its rules', function (assert) {
   448        const mockToken = Service.extend({
   449          aclEnabled: true,
   450          selfToken: { type: 'client' },
   451          selfTokenPolicies: [
   452            {
   453              rulesJSON: {
   454                Namespaces: [
   455                  {
   456                    Name: 'default',
   457                    Capabilities: [],
   458                    Variables: {
   459                      Paths: [{ Capabilities: ['read'], PathSpec: '*' }],
   460                    },
   461                  },
   462                ],
   463              },
   464            },
   465          ],
   466        });
   467  
   468        this.owner.register('service:token', mockToken);
   469  
   470        assert.ok(this.ability.canRead);
   471      });
   472  
   473      test('it handles namespace matching', function (assert) {
   474        const mockToken = Service.extend({
   475          aclEnabled: true,
   476          selfToken: { type: 'client' },
   477          selfTokenPolicies: [
   478            {
   479              rulesJSON: {
   480                Namespaces: [
   481                  {
   482                    Name: 'default',
   483                    Capabilities: [],
   484                    Variables: {
   485                      Paths: [{ Capabilities: ['list'], PathSpec: 'foo/bar' }],
   486                    },
   487                  },
   488                  {
   489                    Name: 'pablo',
   490                    Capabilities: [],
   491                    Variables: {
   492                      Paths: [{ Capabilities: ['read'], PathSpec: 'foo/bar' }],
   493                    },
   494                  },
   495                ],
   496              },
   497            },
   498          ],
   499        });
   500  
   501        this.owner.register('service:token', mockToken);
   502        this.ability.path = 'foo/bar';
   503        this.ability.namespace = 'pablo';
   504  
   505        assert.ok(this.ability.canRead);
   506      });
   507    });
   508  
   509    module('#_nearestMatchingPath', function () {
   510      test('returns capabilities for an exact path match', function (assert) {
   511        const mockToken = Service.extend({
   512          aclEnabled: true,
   513          selfToken: { type: 'client' },
   514          selfTokenPolicies: [
   515            {
   516              rulesJSON: {
   517                Namespaces: [
   518                  {
   519                    Name: 'default',
   520                    Capabilities: [],
   521                    Variables: {
   522                      Paths: [{ Capabilities: ['write'], PathSpec: 'foo' }],
   523                    },
   524                  },
   525                ],
   526              },
   527            },
   528          ],
   529        });
   530  
   531        this.owner.register('service:token', mockToken);
   532        const path = 'foo';
   533  
   534        const nearestMatchingPath = this.ability._nearestMatchingPath(path);
   535  
   536        assert.equal(
   537          nearestMatchingPath,
   538          'foo',
   539          'It should return the exact path match.'
   540        );
   541      });
   542  
   543      test('returns capabilities for the nearest fuzzy match if no exact match', function (assert) {
   544        const mockToken = Service.extend({
   545          aclEnabled: true,
   546          selfToken: { type: 'client' },
   547          selfTokenPolicies: [
   548            {
   549              rulesJSON: {
   550                Namespaces: [
   551                  {
   552                    Name: 'default',
   553                    Capabilities: [],
   554                    Variables: {
   555                      Paths: [
   556                        { Capabilities: ['write'], PathSpec: 'foo/*' },
   557                        { Capabilities: ['write'], PathSpec: 'foo/bar/*' },
   558                      ],
   559                    },
   560                  },
   561                ],
   562              },
   563            },
   564          ],
   565        });
   566  
   567        this.owner.register('service:token', mockToken);
   568        const path = 'foo/bar/baz';
   569  
   570        const nearestMatchingPath = this.ability._nearestMatchingPath(path);
   571  
   572        assert.equal(
   573          nearestMatchingPath,
   574          'foo/bar/*',
   575          'It should return the nearest fuzzy matching path.'
   576        );
   577      });
   578  
   579      test('handles wildcard prefix matches', function (assert) {
   580        const mockToken = Service.extend({
   581          aclEnabled: true,
   582          selfToken: { type: 'client' },
   583          selfTokenPolicies: [
   584            {
   585              rulesJSON: {
   586                Namespaces: [
   587                  {
   588                    Name: 'default',
   589                    Capabilities: [],
   590                    Variables: {
   591                      Paths: [{ Capabilities: ['write'], PathSpec: 'foo/*' }],
   592                    },
   593                  },
   594                ],
   595              },
   596            },
   597          ],
   598        });
   599  
   600        this.owner.register('service:token', mockToken);
   601        const path = 'foo/bar/baz';
   602  
   603        const nearestMatchingPath = this.ability._nearestMatchingPath(path);
   604  
   605        assert.equal(
   606          nearestMatchingPath,
   607          'foo/*',
   608          'It should handle wildcard glob.'
   609        );
   610      });
   611  
   612      test('handles wildcard suffix matches', function (assert) {
   613        const mockToken = Service.extend({
   614          aclEnabled: true,
   615          selfToken: { type: 'client' },
   616          selfTokenPolicies: [
   617            {
   618              rulesJSON: {
   619                Namespaces: [
   620                  {
   621                    Name: 'default',
   622                    Capabilities: [],
   623                    Variables: {
   624                      Paths: [
   625                        { Capabilities: ['write'], PathSpec: '*/bar' },
   626                        { Capabilities: ['write'], PathSpec: '*/bar/baz' },
   627                      ],
   628                    },
   629                  },
   630                ],
   631              },
   632            },
   633          ],
   634        });
   635  
   636        this.owner.register('service:token', mockToken);
   637        const path = 'foo/bar/baz';
   638  
   639        const nearestMatchingPath = this.ability._nearestMatchingPath(path);
   640  
   641        assert.equal(
   642          nearestMatchingPath,
   643          '*/bar/baz',
   644          'It should return the nearest ancestor matching path.'
   645        );
   646      });
   647  
   648      test('prioritizes wildcard suffix matches over wildcard prefix matches', function (assert) {
   649        const mockToken = Service.extend({
   650          aclEnabled: true,
   651          selfToken: { type: 'client' },
   652          selfTokenPolicies: [
   653            {
   654              rulesJSON: {
   655                Namespaces: [
   656                  {
   657                    Name: 'default',
   658                    Capabilities: [],
   659                    Variables: {
   660                      Paths: [
   661                        { Capabilities: ['write'], PathSpec: '*/bar' },
   662                        { Capabilities: ['write'], PathSpec: 'foo/*' },
   663                      ],
   664                    },
   665                  },
   666                ],
   667              },
   668            },
   669          ],
   670        });
   671  
   672        this.owner.register('service:token', mockToken);
   673        const path = 'foo/bar/baz';
   674  
   675        const nearestMatchingPath = this.ability._nearestMatchingPath(path);
   676  
   677        assert.equal(
   678          nearestMatchingPath,
   679          'foo/*',
   680          'It should prioritize suffix glob wildcard of prefix glob wildcard.'
   681        );
   682      });
   683  
   684      test('defaults to the glob path if there is no exact match or wildcard matches', function (assert) {
   685        const mockToken = Service.extend({
   686          aclEnabled: true,
   687          selfToken: { type: 'client' },
   688          selfTokenPolicies: [
   689            {
   690              rulesJSON: {
   691                Namespaces: [
   692                  {
   693                    Name: 'default',
   694                    Capabilities: [],
   695                    Variables: {
   696                      'Path "*"': {
   697                        Capabilities: ['write'],
   698                      },
   699                      'Path "foo"': {
   700                        Capabilities: ['write'],
   701                      },
   702                    },
   703                  },
   704                ],
   705              },
   706            },
   707          ],
   708        });
   709  
   710        this.owner.register('service:token', mockToken);
   711        const path = 'foo/bar/baz';
   712  
   713        const nearestMatchingPath = this.ability._nearestMatchingPath(path);
   714  
   715        assert.equal(
   716          nearestMatchingPath,
   717          '*',
   718          'It should default to glob wildcard if no matches.'
   719        );
   720      });
   721    });
   722  
   723    module('#_computeLengthDiff', function () {
   724      test('should return the difference in length between a path and a pattern', function (assert) {
   725        // arrange
   726        const path = 'foo';
   727        const pattern = 'bar';
   728  
   729        // act
   730        const result = this.ability._computeLengthDiff(pattern, path);
   731  
   732        // assert
   733        assert.equal(
   734          result,
   735          0,
   736          'it returns the difference in length between path and pattern'
   737        );
   738      });
   739  
   740      test('should factor the number of globs into consideration', function (assert) {
   741        // arrange
   742        const pattern = 'foo*';
   743        const path = 'bark';
   744  
   745        // act
   746        const result = this.ability._computeLengthDiff(pattern, path);
   747  
   748        // assert
   749        assert.equal(
   750          result,
   751          1,
   752          'it adds the number of globs in the pattern to the difference'
   753        );
   754      });
   755    });
   756  
   757    module('#_smallestDifference', function () {
   758      test('returns the smallest difference in the list', function (assert) {
   759        // arrange
   760        const path = 'foo/bar';
   761        const matchingPath = 'foo/*';
   762        const matches = ['*/baz', '*', matchingPath];
   763  
   764        // act
   765        const result = this.ability._smallestDifference(matches, path);
   766  
   767        // assert
   768        assert.equal(
   769          result,
   770          matchingPath,
   771          'It should return the smallest difference path.'
   772        );
   773      });
   774    });
   775  
   776    module('#allPaths', function () {
   777      test('it filters by namespace and shows all matching paths on the namespace', function (assert) {
   778        const mockToken = Service.extend({
   779          aclEnabled: true,
   780          selfToken: { type: 'client' },
   781          selfTokenPolicies: [
   782            {
   783              rulesJSON: {
   784                Namespaces: [
   785                  {
   786                    Name: 'default',
   787                    Capabilities: [],
   788                    Variables: {
   789                      Paths: [{ Capabilities: ['write'], PathSpec: 'foo' }],
   790                    },
   791                  },
   792                  {
   793                    Name: 'bar',
   794                    Capabilities: [],
   795                    Variables: {
   796                      Paths: [
   797                        { Capabilities: ['read', 'write'], PathSpec: 'foo' },
   798                      ],
   799                    },
   800                  },
   801                ],
   802              },
   803            },
   804          ],
   805        });
   806  
   807        this.owner.register('service:token', mockToken);
   808        this.ability.namespace = 'bar';
   809  
   810        const allPaths = this.ability.allPaths;
   811  
   812        assert.deepEqual(
   813          allPaths,
   814          [
   815            {
   816              capabilities: ['read', 'write'],
   817              name: 'foo',
   818            },
   819          ],
   820          'It should return the exact path match.'
   821        );
   822      });
   823  
   824      test('it matches on default if no namespace is selected', function (assert) {
   825        const mockToken = Service.extend({
   826          aclEnabled: true,
   827          selfToken: { type: 'client' },
   828          selfTokenPolicies: [
   829            {
   830              rulesJSON: {
   831                Namespaces: [
   832                  {
   833                    Name: 'default',
   834                    Capabilities: [],
   835                    Variables: {
   836                      Paths: [{ Capabilities: ['write'], PathSpec: 'foo' }],
   837                    },
   838                  },
   839                  {
   840                    Name: 'bar',
   841                    Capabilities: [],
   842                    Variables: {
   843                      Paths: [
   844                        { Capabilities: ['read', 'write'], PathSpec: 'foo' },
   845                      ],
   846                    },
   847                  },
   848                ],
   849              },
   850            },
   851          ],
   852        });
   853  
   854        this.owner.register('service:token', mockToken);
   855        this.ability.namespace = undefined;
   856  
   857        const allPaths = this.ability.allPaths;
   858  
   859        assert.deepEqual(
   860          allPaths,
   861          [
   862            {
   863              capabilities: ['write'],
   864              name: 'foo',
   865            },
   866          ],
   867          'It should return the exact path match.'
   868        );
   869      });
   870  
   871      test('it handles globs in namespaces', function (assert) {
   872        const mockToken = Service.extend({
   873          aclEnabled: true,
   874          selfToken: { type: 'client' },
   875          selfTokenPolicies: [
   876            {
   877              rulesJSON: {
   878                Namespaces: [
   879                  {
   880                    Name: '*',
   881                    Capabilities: ['list-jobs', 'alloc-exec', 'read-logs'],
   882                    Variables: {
   883                      Paths: [
   884                        {
   885                          Capabilities: ['list'],
   886                          PathSpec: '*',
   887                        },
   888                      ],
   889                    },
   890                  },
   891                  {
   892                    Name: 'namespace-1',
   893                    Capabilities: ['list-jobs', 'alloc-exec', 'read-logs'],
   894                    Variables: {
   895                      Paths: [
   896                        {
   897                          Capabilities: ['list', 'read', 'destroy', 'create'],
   898                          PathSpec: '*',
   899                        },
   900                      ],
   901                    },
   902                  },
   903                  {
   904                    Name: 'namespace-2',
   905                    Capabilities: ['list-jobs', 'alloc-exec', 'read-logs'],
   906                    Variables: {
   907                      Paths: [
   908                        {
   909                          Capabilities: ['list', 'read', 'destroy', 'create'],
   910                          PathSpec: 'blue/*',
   911                        },
   912                        {
   913                          Capabilities: ['list', 'read', 'create'],
   914                          PathSpec: 'nomad/jobs/*',
   915                        },
   916                      ],
   917                    },
   918                  },
   919                ],
   920              },
   921            },
   922          ],
   923        });
   924  
   925        this.owner.register('service:token', mockToken);
   926        this.ability.namespace = 'pablo';
   927  
   928        const allPaths = this.ability.allPaths;
   929  
   930        assert.deepEqual(
   931          allPaths,
   932          [
   933            {
   934              capabilities: ['list'],
   935              name: '*',
   936            },
   937          ],
   938          'It should return the glob matching namespace match.'
   939        );
   940      });
   941    });
   942  });