Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2a8ddab791 | ||
|
|
32df2d75a6 |
No files matched your search
+17
-17
@@ -11,23 +11,6 @@
|
||||
To configure Data Controller for SAS©, please provide the following details:
|
||||
</p>
|
||||
|
||||
<p class="m-0 mt-10">
|
||||
Please specify a physical directory (on the
|
||||
<strong> {{ SYSHOSTNAME }}</strong>
|
||||
compute server) below, to which user
|
||||
<strong>{{ SYSUSERID }}</strong> can write, on behalf of Data Controller.
|
||||
</p>
|
||||
|
||||
<label for="dcDirectory" class="mt-20 clr-control-label"
|
||||
>DC Staging Directory</label
|
||||
>
|
||||
<div class="mb-10 clr-control-container">
|
||||
<app-dc-location
|
||||
[(path)]="dcDirectory"
|
||||
inputId="dcDirectory"
|
||||
></app-dc-location>
|
||||
</div>
|
||||
|
||||
<p class="m-0 mt-10">
|
||||
Below are the list of groups to which you belong. The group you select will
|
||||
become the Data Controller Admin Group, and everyone in it will have
|
||||
@@ -45,6 +28,23 @@
|
||||
</select>
|
||||
</clr-select-container>
|
||||
|
||||
<p class="m-0 mt-10">
|
||||
Now specify a physical directory (on the
|
||||
<strong> {{ SYSHOSTNAME }}</strong>
|
||||
compute server) below, to which user
|
||||
<strong>{{ SYSUSERID }}</strong> can write, on behalf of Data Controller.
|
||||
</p>
|
||||
|
||||
<label for="dcDirectory" class="mt-20 clr-control-label"
|
||||
>DC Staging Directory</label
|
||||
>
|
||||
<div class="mb-10 clr-control-container">
|
||||
<app-dc-location
|
||||
[(path)]="dcDirectory"
|
||||
inputId="dcDirectory"
|
||||
></app-dc-location>
|
||||
</div>
|
||||
|
||||
<p class="m-0 mt-10">
|
||||
Now, create the target directory and deploy the control library using the
|
||||
admin group selected above:
|
||||
|
||||
+81
@@ -1,4 +1,10 @@
|
||||
import { Component, NO_ERRORS_SCHEMA } from '@angular/core'
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
import { ServerType } from '@sasjs/utils/types/serverType'
|
||||
import { SasjsService } from 'src/app/services/sasjs.service'
|
||||
import { SasService } from 'src/app/services/sas.service'
|
||||
import { DcLocationComponent } from '../dc-location/dc-location.component'
|
||||
import { SasjsConfiguratorComponent } from './sasjs-configurator.component'
|
||||
|
||||
/**
|
||||
@@ -148,3 +154,78 @@ describe('SasjsConfiguratorComponent directory default', () => {
|
||||
expect(await directoryFor('DOCKER')).toBe('/tmp/DataController')
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
* The rendered order. DC on a SASjs Server or SAS9 estate is configured by the
|
||||
* admin group selected here, and the staging directory is the last question
|
||||
* because it is the one the picker has to prove - the same order the Viya
|
||||
* screen asks them in. A template edit that put the directory back on top
|
||||
* would compile and deploy fine and ask the operator to choose a location
|
||||
* before telling DC who administers it.
|
||||
*/
|
||||
describe('SasjsConfiguratorComponent field order', () => {
|
||||
@Component({
|
||||
selector: 'app-sasjs-configurator-host',
|
||||
template: '<app-sasjs-configurator></app-sasjs-configurator>',
|
||||
standalone: false
|
||||
})
|
||||
class HostComponent {}
|
||||
|
||||
let fixture: ComponentFixture<HostComponent>
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [
|
||||
SasjsConfiguratorComponent,
|
||||
HostComponent,
|
||||
DcLocationComponent
|
||||
],
|
||||
imports: [FormsModule],
|
||||
providers: [
|
||||
{
|
||||
provide: SasService,
|
||||
useValue: {
|
||||
getExecutionPath: () => '/SASStoredProcess/do',
|
||||
request: () =>
|
||||
Promise.resolve({ adapterResponse: { SYSSCPL: 'Linux' } }),
|
||||
getSasjsConfig: () => ({}),
|
||||
sasjsMakedataChecking: () => Promise.resolve(false),
|
||||
getUserGroups: () => ({ subscribe: () => undefined }),
|
||||
logout: () => undefined
|
||||
}
|
||||
},
|
||||
{
|
||||
provide: SasjsService,
|
||||
useValue: {
|
||||
getServerInfo: () => ({ subscribe: () => undefined })
|
||||
}
|
||||
}
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
})
|
||||
|
||||
fixture = TestBed.createComponent(HostComponent)
|
||||
fixture.detectChanges()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
TestBed.resetTestingModule()
|
||||
})
|
||||
|
||||
it('asks for the admin group before the staging directory', () => {
|
||||
const labels = Array.from(
|
||||
fixture.nativeElement.querySelectorAll('.clr-control-label')
|
||||
).map((label: unknown) => ((label as HTMLElement).textContent || '').trim())
|
||||
|
||||
const admin = labels.findIndex((l) =>
|
||||
l.toLowerCase().includes('admin group')
|
||||
)
|
||||
const directory = labels.findIndex((l) =>
|
||||
l.toLowerCase().includes('staging directory')
|
||||
)
|
||||
|
||||
expect(admin).toBeGreaterThanOrEqual(0)
|
||||
expect(directory).toBeGreaterThanOrEqual(0)
|
||||
expect(admin).toBeLessThan(directory)
|
||||
})
|
||||
})
|
||||
@@ -30,7 +30,6 @@
|
||||
@li mf_mkdir.sas
|
||||
@li mp_abort.sas
|
||||
@li mpe_action.sas
|
||||
@li ms_getfile.sas
|
||||
@li mpe_dirlist.sas
|
||||
@li mpe_writecheck.sas
|
||||
@li mpe_makedata.sas
|
||||
@@ -274,37 +273,15 @@ run;
|
||||
%mend makedata_body;
|
||||
|
||||
/**
|
||||
* Refuses the browse actions once this appLoc has a settings.sas.
|
||||
* The browse actions need no gate of their own.
|
||||
*
|
||||
* The deploy window closes when MAKEDATA writes that file, and a run that
|
||||
* failed after writing it leaves the file behind - so its presence, not the
|
||||
* survival of this STP, is what says the system is configured. Without this
|
||||
* a failed or abandoned install leaves a caller with a directory listing of
|
||||
* any path the SAS user can read.
|
||||
*
|
||||
* A probe that cannot answer is treated as configured: an unreachable drive
|
||||
* is not evidence that the deployment window is still open.
|
||||
* DIRLIST and WRITECHECK exist for the deploy screen, and the deploy window
|
||||
* closes by itself: a successful run deletes this program, so once DC is
|
||||
* configured there is nothing here left to call. A gate keyed off
|
||||
* settings.sas closed the window on the runs that still needed it - a failed
|
||||
* install leaves that file behind, and so does any earlier configuration of
|
||||
* the same appLoc. That gate closed the very window it was meant to protect.
|
||||
*/
|
||||
%macro browse_gate(iftrue=0);
|
||||
%local status;
|
||||
%if not(&iftrue) %then %return;
|
||||
%let status=0;
|
||||
%ms_getfile(%mf_getapploc()/services/public/settings.sas,outref=dcstngs)
|
||||
%if %symexist(SYS_PROCHTTP_STATUS_CODE) %then
|
||||
%let status=&SYS_PROCHTTP_STATUS_CODE;
|
||||
/* the probe is allowed to 404, so the status is recorded and cleared */
|
||||
%let syscc=0;
|
||||
%mp_abort(iftrue= (&status=200)
|
||||
,mac=&_program
|
||||
,msg=%str(DIRLIST and WRITECHECK are only available until DC is configured)
|
||||
)
|
||||
%mp_abort(iftrue= (&status ne 200 and &status ne 404)
|
||||
,mac=&_program
|
||||
,msg=%str(Could not check whether this appLoc is configured - probe &status)
|
||||
)
|
||||
%mend browse_gate;
|
||||
|
||||
%browse_gate(iftrue= (&action=DIRLIST or &action=WRITECHECK))
|
||||
|
||||
/*
|
||||
Three invocations rather than one branch: each macro takes `iftrue=` and
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
is asserted against the macros directly (macros/mpe_dirlist.test.sas,
|
||||
macros/mpe_writecheck.test.sas); this file covers the dispatch around them.
|
||||
|
||||
The browse actions are only reachable while the appLoc has no settings.sas,
|
||||
and any appLoc running this suite has one - so here the two actions are
|
||||
expected to be refused by the gate. What that proves is that the action
|
||||
reached the gate at all, which is the part the dispatch owns.
|
||||
The browse actions carry no gate of their own: a successful run deletes this
|
||||
program, so the deploy window closes by itself. One of the tests below calls
|
||||
DIRLIST on an appLoc that already has a settings.sas, which is what a retry
|
||||
after a failed install looks like.
|
||||
|
||||
<h4> SAS Macros </h4>
|
||||
@li mpe_assert_abort.sas
|
||||
@@ -82,49 +82,16 @@ run;
|
||||
outds=work.test_results
|
||||
)
|
||||
|
||||
/**
|
||||
* Test 4 - DIRLIST is refused once the appLoc is configured. A run that
|
||||
failed after writing settings.sas leaves it behind, so the file is the
|
||||
test, not the survival of this STP.
|
||||
*/
|
||||
data work.fromjs;
|
||||
length action $10 parent $1000;
|
||||
action='DIRLIST';
|
||||
parent='/tmp';
|
||||
run;
|
||||
%mpe_execute(&_program,
|
||||
viyacontext=&defaultcontext,
|
||||
inputdatasets=work.fromjs,
|
||||
outlib=web4,
|
||||
failfast=0
|
||||
)
|
||||
%mpe_assert_abort(
|
||||
desc=DIRLIST is refused once the appLoc is configured,
|
||||
outstatus=work.dc_childstatus,
|
||||
msg=%str(DIRLIST and WRITECHECK are only available until DC is configured),
|
||||
outds=work.test_results
|
||||
)
|
||||
/*
|
||||
There is no test here for the browse actions themselves.
|
||||
|
||||
/**
|
||||
* Test 5 - and so is WRITECHECK
|
||||
They used to be refused once settings.sas existed, and that refusal is what
|
||||
these two used to assert. The gate is gone: the deploy window closes when a
|
||||
successful run deletes this program, so the window and the program have the
|
||||
same lifetime. DIRLIST and WRITECHECK are asserted against the macros that
|
||||
implement them (macros/mpe_dirlist.test.sas, macros/mpe_writecheck.test.sas);
|
||||
the dispatch around them is what tests 1-3 cover.
|
||||
*/
|
||||
data work.fromjs;
|
||||
length action $10 path $1000;
|
||||
action='WRITECHECK';
|
||||
path='/tmp';
|
||||
run;
|
||||
%mpe_execute(&_program,
|
||||
viyacontext=&defaultcontext,
|
||||
inputdatasets=work.fromjs,
|
||||
outlib=web5,
|
||||
failfast=0
|
||||
)
|
||||
%mpe_assert_abort(
|
||||
desc=WRITECHECK is refused once the appLoc is configured,
|
||||
outstatus=work.dc_childstatus,
|
||||
msg=%str(DIRLIST and WRITECHECK are only available until DC is configured),
|
||||
outds=work.test_results
|
||||
)
|
||||
|
||||
/**
|
||||
* dump results to the log for offline inspection
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
@li mf_trimstr.sas
|
||||
@li mp_abort.sas
|
||||
@li mpe_action.sas
|
||||
@li mfv_existfile.sas
|
||||
@li mpe_dirlist.sas
|
||||
@li mpe_writecheck.sas
|
||||
@li mpe_makedata.sas
|
||||
@@ -366,25 +365,15 @@ run;
|
||||
%mend makedata_body;
|
||||
|
||||
/**
|
||||
* Refuses the browse actions once this appLoc has a settings.sas.
|
||||
* The browse actions need no gate of their own.
|
||||
*
|
||||
* The deploy window closes when MAKEDATA writes that file, and a run that
|
||||
* failed after writing it leaves the file behind - so its presence, not the
|
||||
* survival of this STP, is what says the system is configured. Without this
|
||||
* a failed or abandoned install leaves a caller with a directory listing of
|
||||
* any path the SAS user can read.
|
||||
* DIRLIST and WRITECHECK exist for the deploy screen, and the deploy window
|
||||
* closes by itself: a successful run deletes this program, so once DC is
|
||||
* configured there is nothing here left to call. A gate keyed off
|
||||
* settings.sas closed the window on the runs that still needed it - a failed
|
||||
* install leaves that file behind, and so does any earlier configuration of
|
||||
* the same appLoc. That gate closed the very window it was meant to protect.
|
||||
*/
|
||||
%macro browse_gate(iftrue=0);
|
||||
%local configured;
|
||||
%if not(&iftrue) %then %return;
|
||||
%let configured=%mfv_existfile(%mf_getapploc()/services/settings.sas);
|
||||
%mp_abort(iftrue= (&configured=1)
|
||||
,mac=&_program
|
||||
,msg=%str(DIRLIST and WRITECHECK are only available until DC is configured)
|
||||
)
|
||||
%mend browse_gate;
|
||||
|
||||
%browse_gate(iftrue= (&action=DIRLIST or &action=WRITECHECK))
|
||||
|
||||
/*
|
||||
Three invocations rather than one branch: each macro takes `iftrue=` and
|
||||
|
||||
Reference in new issue
Block a user