Skip to content

Commit b3326c3

Browse files
committed
create publishing destinations
1 parent 0a891fe commit b3326c3

7 files changed

+584
-5
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ Unreleased
55
- Added `create_model_version` and `list_model_versions` to `model_repository`
66
- Added an explicit `ValueError` when attempting to register an ASTORE that can't be downloaded.
77
- Added `start` and `limit` pagination parameters to all default `list_*` service methods.
8+
- Added `create_destination`, `create_cas_destination` and `create_mas_destination` methods for `model_publish` service.
89

910
**Changes**
1011
- `Session.add_stderr_logger` default logging level changed to `DEBUG`.

src/sasctl/_services/model_publish.py

Lines changed: 154 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88

99
import re
1010

11-
from .service import Service
1211
from .model_repository import ModelRepository
12+
from .service import Service
1313

1414

1515
class ModelPublish(Service):
@@ -59,9 +59,13 @@ def list_models(cls):
5959
'destination')
6060

6161
@classmethod
62-
def publish_model(cls, model, destination, name=None, code=None,
62+
def publish_model(cls,
63+
model,
64+
destination,
65+
name=None,
66+
code=None,
6367
notes=None):
64-
"""
68+
"""Publish a model to an existing publishing destination.
6569
6670
Parameters
6771
----------
@@ -118,3 +122,150 @@ def publish_model(cls, model, destination, name=None, code=None,
118122
return cls.post('/models', json=request, headers={
119123
'Content-Type':
120124
'application/vnd.sas.models.publishing.request+json'})
125+
126+
@classmethod
127+
def create_cas_destination(cls, name,
128+
library,
129+
table,
130+
server=None,
131+
description=None):
132+
"""Define a new CAS publishing destination.
133+
134+
Parameters
135+
----------
136+
name : str
137+
Name of the publishing destination.
138+
library : str
139+
The CAS library in which `table` will be stored.
140+
table : str
141+
Name of the CAS table in which models will be stored.
142+
server : str, optional
143+
Name of the CAS server. Defaults to 'cas-shared-default'.
144+
description : str, optional
145+
Description of the publishing destination.
146+
147+
Returns
148+
-------
149+
RestObj
150+
151+
"""
152+
server = server or 'cas-shared-default'
153+
154+
return cls.create_destination(name, cas_server=server,
155+
cas_library=library, cas_table=table,
156+
type_='cas', description=description)
157+
158+
@classmethod
159+
def create_mas_destination(cls, name, uri, description=None):
160+
"""Define a new Micro Analytic Server (MAS) publishing destination.
161+
162+
Parameters
163+
----------
164+
name : str
165+
Name of the publishing destination.
166+
uri : str
167+
The base URI that contains the host, the protocol, and optionally
168+
the port, which addresses the remote SAS Micro Analytic Service to
169+
use. Example: http://spam.com
170+
description : str, optional
171+
Description of the publishing destination.
172+
173+
Returns
174+
-------
175+
RestObj
176+
177+
"""
178+
return cls.create_destination(name, mas_uri=uri, type_='mas',
179+
description=description)
180+
181+
@classmethod
182+
def create_destination(cls,
183+
name,
184+
type_,
185+
cas_server=None,
186+
cas_library=None,
187+
cas_table=None,
188+
description=None,
189+
mas_uri=None,
190+
hdfs_dir=None,
191+
conf_dir=None,
192+
user=None,
193+
database_library=None):
194+
"""Define a new publishing destination.
195+
196+
Parameters
197+
----------
198+
name : str
199+
Name of the publishing destination.
200+
type_ : {'cas', 'mas', 'hadoop', 'teradata'}
201+
Type of publishing definition being created
202+
cas_server : str, optional
203+
Name of the CAS server. Defaults to 'cas-shared-default'.
204+
Required if `type_` is 'cas', otherwise ignored.
205+
cas_library : str, optional
206+
The CAS library in which `cas_table` will be stored. Required if
207+
`type_` is 'cas', otherwise ignored.
208+
cas_table : str, optional
209+
Name of the CAS table in which models will be stored. Required
210+
if `type_` is 'cas', otherwise ignored.
211+
description : str, optional
212+
Description of the publishing destination.
213+
mas_uri : str, optional
214+
Required if `type_` is 'mas', otherwise ignored.
215+
hdfs_dir : str, optional
216+
Required if `type_` is 'hadoop', otherwise ignored.
217+
conf_dir : str, optional
218+
Required if `type_` is 'hadoop', otherwise ignored.
219+
user : str, optional
220+
Required if `type_` is 'hadoop', otherwise ignored.
221+
database_library : str, optional
222+
Required if `type_` is 'teradata', otherwise ignored.
223+
224+
Returns
225+
-------
226+
RestObj
227+
228+
"""
229+
type_ = str(type_).lower()
230+
assert type_ in ('cas', 'microanalyticservice', 'mas',
231+
'teradata', 'hadoop')
232+
233+
# As of Viya 3.4 capitalization matters.
234+
if type_ in ('microanalyticservice', 'mas'):
235+
type_ = 'microAnalyticService'
236+
237+
request = {'name': str(name),
238+
'destinationType': type_,
239+
'casServerName': cas_server,
240+
'casLibrary': cas_library,
241+
'description': description,
242+
'destinationTable': cas_table,
243+
'databaseCasLibrary': database_library,
244+
'user': user,
245+
'hdfsDirectory': hdfs_dir,
246+
'configurationDirectory': conf_dir,
247+
'masUri': mas_uri
248+
}
249+
250+
drop_list = {
251+
'cas':
252+
('databaseCasLibrary', 'user', 'hdfsDirectory', 'masUri',
253+
'configurationDirectory'),
254+
'microAnalyticService':
255+
('casServerName', 'casLibrary', 'destinationTable', 'user',
256+
'databaseCasLibrary', 'hdfsDirectory',
257+
'configurationDirectory'),
258+
'hadoop':
259+
('casServerName', 'casLibrary', 'destinationTable',
260+
'databaseCasLibrary', 'masUri'),
261+
'teradata':
262+
('casServerName', 'casLibrary', 'destinationTable', 'user',
263+
'hdfsDirectory', 'masUri', 'configurationDirectory')
264+
}
265+
266+
for k in drop_list[request['destinationType']]:
267+
request.pop(k, None)
268+
269+
return cls.post('/destinations', json=request, headers={
270+
'Content-Type':
271+
'application/vnd.sas.models.publishing.destination+json'})
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
{
2+
"http_interactions": [
3+
{
4+
"recorded_at": "2019-08-16T16:59:52",
5+
"request": {
6+
"body": {
7+
"encoding": "utf-8",
8+
"string": "grant_type=password&username=USERNAME&password=*****"
9+
},
10+
"headers": {
11+
"Accept": [
12+
"application/json"
13+
],
14+
"Accept-Encoding": [
15+
"gzip, deflate"
16+
],
17+
"Authorization": [
18+
"Basic [redacted]"
19+
],
20+
"Connection": [
21+
"keep-alive"
22+
],
23+
"Content-Length": [
24+
"54"
25+
],
26+
"Content-Type": [
27+
"application/x-www-form-urlencoded"
28+
],
29+
"User-Agent": [
30+
"python-requests/2.22.0"
31+
]
32+
},
33+
"method": "POST",
34+
"uri": "https://hostname.com/SASLogon/oauth/token"
35+
},
36+
"response": {
37+
"body": {
38+
"encoding": "UTF-8",
39+
"string": "{\"access_token\":\"[redacted]\",\"token_type\":\"bearer\",\"expires_in\":35999,\"scope\":\"DataBuilders ApplicationAdministrators qasDataAdmin qasFQAAnalyst SASScoreUsers qasAPAAnalyst qasInfoConsumer clients.read clients.secret uaa.resource openid uaa.admin clients.admin EsriUsers scim.read SASAdministrators qasPQAAnalyst clients.write scim.write qasAppAdmin CASHostAccountRequired\",\"jti\":\"2056c99c8bab4bc28bba7febd8ccaf88\"}"
40+
},
41+
"headers": {
42+
"Cache-Control": [
43+
"no-cache, no-store, max-age=0, must-revalidate",
44+
"no-store"
45+
],
46+
"Connection": [
47+
"Keep-Alive"
48+
],
49+
"Content-Type": [
50+
"application/json;charset=UTF-8"
51+
],
52+
"Date": [
53+
"Fri, 16 Aug 2019 16:59:52 GMT"
54+
],
55+
"Expires": [
56+
"0"
57+
],
58+
"Keep-Alive": [
59+
"timeout=5, max=100"
60+
],
61+
"Pragma": [
62+
"no-cache",
63+
"no-cache"
64+
],
65+
"Strict-Transport-Security": [
66+
"max-age=31536000 ; includeSubDomains"
67+
],
68+
"Transfer-Encoding": [
69+
"chunked"
70+
],
71+
"Vary": [
72+
"User-Agent"
73+
],
74+
"X-Content-Type-Options": [
75+
"nosniff"
76+
],
77+
"X-Frame-Options": [
78+
"DENY"
79+
],
80+
"X-XSS-Protection": [
81+
"1; mode=block"
82+
]
83+
},
84+
"status": {
85+
"code": 200,
86+
"message": ""
87+
},
88+
"url": "https://hostname.com/SASLogon/oauth/token"
89+
}
90+
},
91+
{
92+
"recorded_at": "2019-08-16T16:59:52",
93+
"request": {
94+
"body": {
95+
"encoding": "utf-8",
96+
"string": "{\"name\": \"caslocal\", \"destinationType\": \"cas\", \"casServerName\": \"cas-shared-default\", \"casLibrary\": \"Public\", \"description\": \"Test CAS publish destination from sasctl.\", \"destinationTable\": \"sasctl_models\"}"
97+
},
98+
"headers": {
99+
"Accept": [
100+
"*/*"
101+
],
102+
"Accept-Encoding": [
103+
"gzip, deflate"
104+
],
105+
"Authorization": [
106+
"Bearer [redacted]"
107+
],
108+
"Connection": [
109+
"keep-alive"
110+
],
111+
"Content-Length": [
112+
"206"
113+
],
114+
"Content-Type": [
115+
"application/vnd.sas.models.publishing.destination+json"
116+
],
117+
"User-Agent": [
118+
"python-requests/2.22.0"
119+
]
120+
},
121+
"method": "POST",
122+
"uri": "https://hostname.com/modelPublish/destinations"
123+
},
124+
"response": {
125+
"body": {
126+
"encoding": "UTF-8",
127+
"string": "{\"creationTimeStamp\":\"2019-08-16T16:59:52.735Z\",\"modifiedTimeStamp\":\"2019-08-16T16:59:52.735Z\",\"createdBy\":\"USERNAME\",\"modifiedBy\":\"USERNAME\",\"id\":\"94140311-6993-4c65-9bf4-a48a1f64291c\",\"links\":[{\"method\":\"GET\",\"rel\":\"up\",\"href\":\"/modelPublish/destinations\",\"uri\":\"/modelPublish/destinations\",\"type\":\"application/vnd.sas.collection\"},{\"method\":\"GET\",\"rel\":\"self\",\"href\":\"/modelPublish/destinations/caslocal\",\"uri\":\"/modelPublish/destinations/caslocal\",\"type\":\"application/vnd.sas.models.publishing.destination\"},{\"method\":\"PUT\",\"rel\":\"update\",\"href\":\"/modelPublish/destinations/caslocal\",\"uri\":\"/modelPublish/destinations/caslocal\",\"type\":\"application/vnd.sas.models.publishing.destination\"},{\"method\":\"DELETE\",\"rel\":\"delete\",\"href\":\"/modelPublish/destinations/caslocal\",\"uri\":\"/modelPublish/destinations/caslocal\"}],\"version\":1,\"name\":\"caslocal\",\"description\":\"Test CAS publish destination from sasctl.\",\"destinationType\":\"cas\",\"destinationTable\":\"sasctl_models\",\"casServerName\":\"cas-shared-default\",\"casLibrary\":\"Public\"}"
128+
},
129+
"headers": {
130+
"Cache-Control": [
131+
"no-cache, no-store, max-age=0, must-revalidate"
132+
],
133+
"Connection": [
134+
"Keep-Alive"
135+
],
136+
"Content-Security-Policy": [
137+
"default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; img-src 'self' *.sas.com blob: data:; style-src 'self' 'unsafe-inline'; child-src 'self' blob: data: mailto:;"
138+
],
139+
"Content-Type": [
140+
"application/vnd.sas.models.publishing.destination+json;charset=UTF-8"
141+
],
142+
"Date": [
143+
"Fri, 16 Aug 2019 16:59:52 GMT"
144+
],
145+
"Expires": [
146+
"0"
147+
],
148+
"Keep-Alive": [
149+
"timeout=5, max=99"
150+
],
151+
"Location": [
152+
"/modelPublish/destinations/caslocal"
153+
],
154+
"Pragma": [
155+
"no-cache"
156+
],
157+
"Strict-Transport-Security": [
158+
"max-age=31536000 ; includeSubDomains"
159+
],
160+
"Transfer-Encoding": [
161+
"chunked"
162+
],
163+
"Vary": [
164+
"User-Agent"
165+
],
166+
"X-Content-Type-Options": [
167+
"nosniff"
168+
],
169+
"X-Frame-Options": [
170+
"SAMEORIGIN"
171+
],
172+
"X-XSS-Protection": [
173+
"1; mode=block"
174+
]
175+
},
176+
"status": {
177+
"code": 201,
178+
"message": ""
179+
},
180+
"url": "https://hostname.com/modelPublish/destinations"
181+
}
182+
}
183+
],
184+
"recorded_with": "betamax/0.8.1"
185+
}

0 commit comments

Comments
 (0)