From 141f83ca7323e7cdc038c8eb47bd8cfd76a45826 Mon Sep 17 00:00:00 2001 From: Gerry Nelson <45608078+gerrynelson63@users.noreply.github.com> Date: Mon, 2 Aug 2021 12:34:51 -0400 Subject: [PATCH] Feature/exportimport (#86) * first pass export groups * export import cas auth * updates * message * no caslib message --- exportcaslibs.py | 139 ++++++++++++++++++++++++++++++++++++++++++ exportcustomgroups.py | 119 ++++++++++++++++++++++++++++++++++++ importcaslibs.py | 41 ++++++++++--- 3 files changed, 292 insertions(+), 7 deletions(-) create mode 100755 exportcaslibs.py create mode 100755 exportcustomgroups.py diff --git a/exportcaslibs.py b/exportcaslibs.py new file mode 100755 index 0000000..95276b5 --- /dev/null +++ b/exportcaslibs.py @@ -0,0 +1,139 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# listcaslibs.py +# January 2019 +# +# Usage: +# listcaslibs.py [--noheader] [-d] +# +# Examples: +# +# 1. Return list of all CAS libraries on all servers +# ./listcaslibs.py +# +# Copyright © 2019, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the License); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +debug=False + +# Import Python modules +import argparse, json, sys, os, glob +from sharedfunctions import callrestapi + +# get python version +version=int(str(sys.version_info[0])) + +parser = argparse.ArgumentParser() +parser.add_argument("-s","--server", help="CAS Server (default is cas-shared-default)",default="cas-shared-default") +parser.add_argument("-i","--includeauthorization", help="Also export caslib authorization",action='store_true') +parser.add_argument("-d","--directory", help="Directory where packages are written.",required='True') +parser.add_argument("-nc","--namecontains", help="Name contains",default=None) +parser.add_argument("-dc","--descriptioncontains", help="Name contains",default=None) +parser.add_argument("-q","--quiet", help="Suppress the are you sure prompt.", action='store_true') +parser.add_argument("--debug", action='store_true', help="Debug") + +args = parser.parse_args() +debug=args.debug +server=args.server +basedir=args.directory +quietmode=args.quiet +includeauthorization=args.includeauthorization +nameval=args.namecontains +descval=args.descriptioncontains + +delimiter=',' +# create a list for filter conditions +filtercond=[] + +if nameval!=None: filtercond.append('contains(name,"'+nameval+'")') +if descval!=None: filtercond.append('contains(description,"'+descval+'")') + + +if len(filtercond)>1: + completefilter = 'and('+delimiter.join(filtercond)+')' +elif len(filtercond)==1: + if nameval!=None: completefilter='contains(name,"'+nameval+'")' + if descval!=None: completefilter='contains(description,"'+descval+'")' + +if len(filtercond)==0: completefilter=str() +else: completefilter='&filter='+completefilter + +# prompt if directory exists because existing json files are deleted +if os.path.exists(basedir): + + # if the quiet mode flag is not passed then prompt to continue + if not quietmode: + + if version > 2: + areyousure=input("The folder exists any existing json files in it will be deleted. Continue? (Y)") + else: + areyousure=raw_input("he folder exists any existing json files in it will be deleted. Continue? (Y)") + else: + areyousure="Y" +else: areyousure="Y" + +# prompt is Y if user selected Y, its a new directory, or user selected quiet mode +if areyousure.upper() =='Y': + + path=basedir + + # List the caslibs in this server + endpoint='/casManagement/servers/'+server+'/caslibs?excludeItemLinks=true&limit=10000'+completefilter + if debug: print(endpoint) + method='get' + caslibs_result_json=callrestapi(endpoint,method) + caslibs=caslibs_result_json['items'] + + if len(caslibs): + + if not os.path.exists(path): os.makedirs(path) + else: + filelist=glob.glob(path+"/*.json") + + for file in filelist: + os.remove(file) + + # loop the caslibs and output a json file + for caslib in caslibs: + + caslib['server']=server + caslibname=caslib['name'] + #print(json.dumps( caslib,indent=2)) + fullfile=os.path.join(basedir,caslibname+'.json') + outfile=open(fullfile, "w") + json.dump(caslib, outfile) + + # optionally export caslib authorization + if includeauthorization: + method='get' + endpoint='/casAccessManagement/servers/'+server+'/caslibControls/'+caslibname+'?excludeItemLinks=true&limit=10000' + casauth_result=callrestapi(endpoint,method) + + authfile=os.path.join(basedir,caslibname+'_authorization_.json') + outauth=open(authfile, "w") + + # delete metadata items before writing file + if 'name' in casauth_result: casauth_result.pop('name') + if 'count' in casauth_result: casauth_result.pop('count') + if 'start' in casauth_result: casauth_result.pop('start') + if 'limit' in casauth_result: casauth_result.pop('limit') + + json.dump(casauth_result, outauth) + +if len(caslibs): + print("NOTE: caslib definitions written to "+basedir) + if includeauthorization: print("NOTE: Authorization files included.") +else: print("NOTE: no caslibs found.") \ No newline at end of file diff --git a/exportcustomgroups.py b/exportcustomgroups.py new file mode 100755 index 0000000..af974d2 --- /dev/null +++ b/exportcustomgroups.py @@ -0,0 +1,119 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# exportcustomgroups.py +# Feb 2021 +# +# Pass in a customgroups and this tool will export the customgroups to a apcakge +# +# +# Change History +# +# +# Copyright © 2019, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the License); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Import Python modules +import argparse, sys, subprocess, uuid, time, os, glob, json, tempfile + +from sharedfunctions import getfolderid, callrestapi, getapplicationproperties, printresult + +# get python version +version=int(str(sys.version_info[0])) + +# get cli location from properties +propertylist=getapplicationproperties() + +clidir=propertylist["sascli.location"] +cliexe=propertylist["sascli.executable"] + +clicommand=os.path.join(clidir,cliexe) + +tempdir=tempfile.gettempdir() + +# get input parameters +parser = argparse.ArgumentParser(description="Export Custom Groups to a Package") + +parser.add_argument("-f","--filename", help="Full path to file. (No extension)",default="/tmp/customgroups") +parser.add_argument("-d","--debug", action='store_true', help="Debug") + + +args= parser.parse_args() + +filename=args.filename +debug=args.debug + +# create the requests file of the custom groups + +# get all groups that are custom +reqtype='get' +reqval='/identities/groups/?filter=eq(providerId,"local")&limit=10000' +groupslist_result_json=callrestapi(reqval,reqtype) + +groups = groupslist_result_json['items'] + +#if debug: print(json.dumps(groups,indent=2)) + +""" This is the json format { +"version": 1, +"name": "Modelers", +"description": "Modelers", +"items": [ "/identities/groups/SalesModelers", + "/identities/groups/HRModelers" + ] +} """ + +basename = os.path.basename(filename) + +requests_dict={"version":1} +requests_dict["name"]=basename +requests_dict["description"]="Custom Groups from pyviyatools "+basename + +grouplist=[] + +# create a dictionary that will generate the requests file +for group in groups: + + group_uri="/identities/groups/"+group['id'] + grouplist.append(group_uri) + +requests_dict["items"]=grouplist + +if debug: print(json.dumps(requests_dict,indent=2)) + +# build the requests file from the list + +request_file=os.path.join(tempdir,filename+"_requests.json") + +with open(request_file, "w") as outfile: + json.dump(requests_dict, outfile) + +# export the groups to a package file + +command=clicommand+' transfer export -r @'+request_file+' --name "'+basename+'"' + +print(command) +subprocess.call(command, shell=True) + +reqtype='get' +reqval='/transfer/packages?filter=eq(name,"'+basename+'")' +package_info=callrestapi(reqval,reqtype) +package_id=package_info['items'][0]['id'] + +completefile=os.path.join(filename+'.json') +command=clicommand+' transfer download --file '+completefile+' --id '+package_id + +print(command) +subprocess.call(command, shell=True) diff --git a/importcaslibs.py b/importcaslibs.py index 2bbf3e5..b49bff3 100755 --- a/importcaslibs.py +++ b/importcaslibs.py @@ -32,7 +32,7 @@ # # Import Python modules import argparse, sys, subprocess, os, json -from sharedfunctions import callrestapi, getapplicationproperties +from sharedfunctions import callrestapi, getapplicationproperties, file_accessible # get cli location from properties propertylist=getapplicationproperties() @@ -63,6 +63,8 @@ if not quietmode: else: areyousure="Y" +tryimport=0 + if areyousure.upper() =='Y': # check that directory exists @@ -71,17 +73,42 @@ if areyousure.upper() =='Y': # loop files in the directory for filename in os.listdir( basedir ): + fullfile=os.path.join(basedir,filename) + # only process json files if filename.lower().endswith('.json'): - command=clicommand+' cas caslibs create path --source-file '+os.path.join(basedir,filename) - print(command) - subprocess.call(command, shell=True) - print("NOTE: Viya Caslib imported attempted from json file "+filename+" in directory "+basedir ) + #create the caslib + if '_authorization_' not in filename: + + # get some caslib attributes for the authorization import + with open(fullfile) as json_file: + data = json.load(json_file) + + caslibname=data['name'] + casserver=data['server'] + + command=clicommand+' cas caslibs create path --source-file '+fullfile + print("NOTE: Viya Caslib import attempted from json file "+filename+" in directory "+basedir ) + print(command) + subprocess.call(command, shell=True) + tryimport=tryimport+1 + + # apply the authorization if authorization file exists + authfile=os.path.join(basedir,caslibname+'_authorization_.json') + access_file=file_accessible(authfile,'r') + + if access_file==True: + command=clicommand+' cas caslibs replace-controls --server '+casserver+' --name '+ caslibname+' --force --source-file '+authfile + print("NOTE: Viya Caslib authorization import attempted from json file "+filename+" in directory "+basedir ) + print(command) + subprocess.call(command, shell=True) + + if not tryimport: print("NOTE: no caslib files available for import.") - else: print("ERROR: Directory does not exist") + else: print("ERROR: Directory does not exist.") else: - print("NOTE: Operation cancelled") + print("NOTE: Operation cancelled.")