2020-06-09 21:03:28 +00:00
/* eslint-disable ember/avoid-leaking-state-in-ember-objects */
2020-01-20 20:57:01 +00:00
import { module , test } from 'qunit' ;
import { setupTest } from 'ember-qunit' ;
import Service from '@ember/service' ;
2020-01-28 01:32:29 +00:00
import setupAbility from 'nomad-ui/tests/helpers/setup-ability' ;
2020-01-20 20:57:01 +00:00
module ( 'Unit | Ability | job' , function ( hooks ) {
setupTest ( hooks ) ;
2020-01-28 01:32:29 +00:00
setupAbility ( 'job' ) ( hooks ) ;
2020-01-20 20:57:01 +00:00
2020-01-31 00:34:35 +00:00
test ( 'it permits job run when ACLs are disabled' , function ( assert ) {
const mockToken = Service . extend ( {
aclEnabled : false ,
} ) ;
this . owner . register ( 'service:token' , mockToken ) ;
assert . ok ( this . ability . canRun ) ;
} ) ;
2020-01-20 20:57:01 +00:00
test ( 'it permits job run for management tokens' , function ( assert ) {
const mockToken = Service . extend ( {
2020-01-31 00:34:35 +00:00
aclEnabled : true ,
2020-01-20 20:57:01 +00:00
selfToken : { type : 'management' } ,
} ) ;
this . owner . register ( 'service:token' , mockToken ) ;
2020-01-28 01:32:29 +00:00
assert . ok ( this . ability . canRun ) ;
2020-01-20 20:57:01 +00:00
} ) ;
test ( 'it permits job run for client tokens with a policy that has namespace submit-job' , function ( assert ) {
const mockSystem = Service . extend ( {
2020-01-31 00:34:35 +00:00
aclEnabled : true ,
2020-01-20 20:57:01 +00:00
} ) ;
const mockToken = Service . extend ( {
2020-01-31 00:34:35 +00:00
aclEnabled : true ,
2020-01-20 20:57:01 +00:00
selfToken : { type : 'client' } ,
selfTokenPolicies : [
{
rulesJSON : {
Namespaces : [
{
Name : 'aNamespace' ,
Capabilities : [ 'submit-job' ] ,
} ,
] ,
} ,
} ,
] ,
} ) ;
this . owner . register ( 'service:system' , mockSystem ) ;
this . owner . register ( 'service:token' , mockToken ) ;
2021-04-29 20:00:59 +00:00
assert . ok ( this . can . can ( 'run job' , null , { namespace : 'aNamespace' } ) ) ;
2020-01-20 20:57:01 +00:00
} ) ;
test ( 'it permits job run for client tokens with a policy that has default namespace submit-job and no capabilities for active namespace' , function ( assert ) {
const mockSystem = Service . extend ( {
2020-01-31 00:34:35 +00:00
aclEnabled : true ,
2020-01-20 20:57:01 +00:00
} ) ;
const mockToken = Service . extend ( {
2020-01-31 00:34:35 +00:00
aclEnabled : true ,
2020-01-20 20:57:01 +00:00
selfToken : { type : 'client' } ,
selfTokenPolicies : [
{
rulesJSON : {
Namespaces : [
{
Name : 'aNamespace' ,
Capabilities : [ ] ,
} ,
{
Name : 'default' ,
Capabilities : [ 'submit-job' ] ,
} ,
] ,
} ,
} ,
] ,
} ) ;
this . owner . register ( 'service:system' , mockSystem ) ;
this . owner . register ( 'service:token' , mockToken ) ;
2021-04-29 20:00:59 +00:00
assert . ok ( this . can . can ( 'run job' , null , { namespace : 'anotherNamespace' } ) ) ;
2020-01-20 20:57:01 +00:00
} ) ;
test ( 'it blocks job run for client tokens with a policy that has no submit-job capability' , function ( assert ) {
const mockSystem = Service . extend ( {
2020-01-31 00:34:35 +00:00
aclEnabled : true ,
2020-01-20 20:57:01 +00:00
} ) ;
const mockToken = Service . extend ( {
2020-01-31 00:34:35 +00:00
aclEnabled : true ,
2020-01-20 20:57:01 +00:00
selfToken : { type : 'client' } ,
selfTokenPolicies : [
{
rulesJSON : {
Namespaces : [
{
Name : 'aNamespace' ,
Capabilities : [ 'list-jobs' ] ,
} ,
] ,
} ,
} ,
] ,
} ) ;
this . owner . register ( 'service:system' , mockSystem ) ;
this . owner . register ( 'service:token' , mockToken ) ;
2021-04-29 20:00:59 +00:00
assert . ok ( this . can . cannot ( 'run job' , null , { namespace : 'aNamespace' } ) ) ;
2020-01-20 20:57:01 +00:00
} ) ;
2020-06-18 05:44:35 +00:00
test ( 'job scale requires a client token with the submit-job or scale-job capability' , function ( assert ) {
const makePolicies = ( namespace , ... capabilities ) => [
{
rulesJSON : {
Namespaces : [
{
Name : namespace ,
Capabilities : capabilities ,
} ,
] ,
} ,
} ,
] ;
const mockSystem = Service . extend ( {
aclEnabled : true ,
} ) ;
const mockToken = Service . extend ( {
aclEnabled : true ,
selfToken : { type : 'client' } ,
selfTokenPolicies : makePolicies ( 'aNamespace' ) ,
} ) ;
this . owner . register ( 'service:system' , mockSystem ) ;
this . owner . register ( 'service:token' , mockToken ) ;
const tokenService = this . owner . lookup ( 'service:token' ) ;
2021-04-29 20:00:59 +00:00
assert . ok ( this . can . cannot ( 'scale job' , null , { namespace : 'aNamespace' } ) ) ;
2020-06-18 05:44:35 +00:00
tokenService . set ( 'selfTokenPolicies' , makePolicies ( 'aNamespace' , 'scale-job' ) ) ;
2021-04-29 20:00:59 +00:00
assert . ok ( this . can . can ( 'scale job' , null , { namespace : 'aNamespace' } ) ) ;
2020-06-18 05:44:35 +00:00
tokenService . set ( 'selfTokenPolicies' , makePolicies ( 'aNamespace' , 'submit-job' ) ) ;
2021-04-29 20:00:59 +00:00
assert . ok ( this . can . can ( 'scale job' , null , { namespace : 'aNamespace' } ) ) ;
2020-06-18 05:44:35 +00:00
tokenService . set ( 'selfTokenPolicies' , makePolicies ( 'bNamespace' , 'scale-job' ) ) ;
2021-04-29 20:00:59 +00:00
assert . ok ( this . can . cannot ( 'scale job' , null , { namespace : 'aNamespace' } ) ) ;
2020-06-18 05:44:35 +00:00
} ) ;
2021-07-20 22:27:41 +00:00
test ( 'job dispatch requires a client token with the dispatch-job capability' , function ( assert ) {
const makePolicies = ( namespace , ... capabilities ) => [
{
rulesJSON : {
Namespaces : [
{
Name : namespace ,
Capabilities : capabilities ,
} ,
] ,
} ,
} ,
] ;
const mockSystem = Service . extend ( {
aclEnabled : true ,
} ) ;
const mockToken = Service . extend ( {
aclEnabled : true ,
selfToken : { type : 'client' } ,
selfTokenPolicies : makePolicies ( 'aNamespace' ) ,
} ) ;
this . owner . register ( 'service:system' , mockSystem ) ;
this . owner . register ( 'service:token' , mockToken ) ;
const tokenService = this . owner . lookup ( 'service:token' ) ;
assert . ok ( this . can . cannot ( 'dispatch job' , null , { namespace : 'aNamespace' } ) ) ;
tokenService . set ( 'selfTokenPolicies' , makePolicies ( 'aNamespace' , 'dispatch-job' ) ) ;
assert . ok ( this . can . can ( 'dispatch job' , null , { namespace : 'aNamespace' } ) ) ;
} ) ;
2020-01-20 20:57:01 +00:00
test ( 'it handles globs in namespace names' , function ( assert ) {
const mockSystem = Service . extend ( {
2020-01-31 00:34:35 +00:00
aclEnabled : true ,
2020-01-20 20:57:01 +00:00
} ) ;
const mockToken = Service . extend ( {
2020-01-31 00:34:35 +00:00
aclEnabled : true ,
2020-01-20 20:57:01 +00:00
selfToken : { type : 'client' } ,
selfTokenPolicies : [
{
rulesJSON : {
Namespaces : [
{
Name : 'production-*' ,
Capabilities : [ 'submit-job' ] ,
} ,
{
Name : 'production-api' ,
Capabilities : [ 'submit-job' ] ,
} ,
{
Name : 'production-web' ,
Capabilities : [ ] ,
} ,
{
Name : '*-suffixed' ,
Capabilities : [ 'submit-job' ] ,
} ,
{
Name : '*-more-suffixed' ,
Capabilities : [ ] ,
} ,
{
Name : '*-abc-*' ,
Capabilities : [ 'submit-job' ] ,
} ,
] ,
} ,
} ,
] ,
} ) ;
this . owner . register ( 'service:system' , mockSystem ) ;
this . owner . register ( 'service:token' , mockToken ) ;
2021-04-29 20:00:59 +00:00
assert . ok ( this . can . cannot ( 'run job' , null , { namespace : 'production-web' } ) ) ;
assert . ok ( this . can . can ( 'run job' , null , { namespace : 'production-api' } ) ) ;
assert . ok ( this . can . can ( 'run job' , null , { namespace : 'production-other' } ) ) ;
assert . ok ( this . can . can ( 'run job' , null , { namespace : 'something-suffixed' } ) ) ;
assert . ok (
this . can . cannot ( 'run job' , null , { namespace : 'something-more-suffixed' } ) ,
2020-01-20 20:57:01 +00:00
'expected the namespace with the greatest number of matched characters to be chosen'
) ;
2021-04-29 20:00:59 +00:00
assert . ok (
this . can . can ( 'run job' , null , { namespace : '000-abc-999' } ) ,
'expected to be able to match against more than one wildcard'
) ;
2020-01-20 20:57:01 +00:00
} ) ;
} ) ;