def run_command(args): logger = log(__class__.__name__, args.logging_level) logger.debug(_("tabcmd.launching")) session = Session() server = session.create_session(args) logger.info(_("delete.status").format(args.name, "")) error = None try: item_to_delete = DeleteCommand.get_workbook_item( logger, server, args.name) item_type = "workbook" except TSC.ServerResponseError as workbook_error: error = workbook_error try: item_to_delete = DeleteCommand.get_data_source_item( logger, server, args.name) item_type = "datasource" except TSC.ServerResponseError as ds_error: error = ds_error if not item_type: logger.debug(error) Errors.exit_with_error( logger, _("delete.errors.requires_workbook_datasource")) try: if item_type == "workbook": server.workbooks.delete(item_to_delete.id) else: server.datasources.delete(item_to_delete.id) logger.info(_("common.output.succeeded")) except TSC.ServerResponseError as e: Errors.exit_with_error(logger, "Error deleting from server", e)
def run_command(args): logger = log(__class__.__name__, args.logging_level) logger.debug(_("tabcmd.launching")) session = Session() server = session.create_session(args) if args.parent_project_path: logger.debug("parent path: {}".format(args.parent_project_path)) try: logger.debug( _("deleteproject.status").format(args.parent_project_path, args.project_name)) project = Server.get_project_by_name_and_parent_path( logger, server, args.project_name, args.parent_project_path) except TSC.ServerResponseError as e: Errors.exit_with_error( logger, _("publish.errors.unexpected_server_response"), e) project_id = project.id try: logger.info(_("deleteproject.status").format(args.project_name)) server.projects.delete(project_id) logger.info(_("common.output.succeeded")) except TSC.ServerResponseError as e: Errors.exit_with_error(logger, "tabcmd.result.failure.delete.project", e)
def _read_from_json(self): if not self._check_json(): return file_path = self._get_file_path() data = {} with open(str(file_path), "r") as file_contents: data = json.load(file_contents) try: for auth in data["tableau_auth"]: self.auth_token = auth["auth_token"] self.server_url = auth["server"] self.site_name = auth["site_name"] self.site_id = auth["site_id"] self.username = auth["username"] self.user_id = auth["user_id"] self.token_name = auth["personal_access_token_name"] self.token = auth["personal_access_token"] self.last_login_using = auth["last_login_using"] self.password_file = auth["password_file"] self.no_prompt = auth["no_prompt"] self.no_certcheck = auth["no_certcheck"] self.certificate = auth["certificate"] self.no_proxy = auth["no_proxy"] self.proxy = auth["proxy"] self.timeout = auth["timeout"] except KeyError as e: self.logger.debug(_("sessionoptions.errors.bad_password_file"), e) self._remove_json() except Exception as any_error: self.logger.info(_("session.new_session")) self._remove_json()
def run_command(args): # A view can be returned in PDF, PNG, or CSV (summary data only) format. # A Tableau workbook is returned as a TWB if it connects to a datasource/live connection, # or a TWBX if it uses an extract. logger = log(__class__.__name__, args.logging_level) logger.debug(_("tabcmd.launching")) session = Session() server = session.create_session(args) if " " in args.url: Errors.exit_with_error( logger, _("export.errors.white_space_workbook_view")) file_type = GetUrl.get_file_type_from_filename(logger, args.filename, args.url) content_type = GetUrl.evaluate_content_type(logger, args.url) if content_type == "workbook": if file_type == "twbx" or file_type == "twb": GetUrl.generate_twb(logger, server, args, file_type) else: Errors.exit_with_error( logger, message=_( "publish.errors.mutually_exclusive_option").format( "twb", "twbx")) else: # content type = view if file_type == "pdf": GetUrl.generate_pdf(logger, server, args) elif file_type == "png": GetUrl.generate_png(logger, server, args) elif file_type == "csv": GetUrl.generate_csv(logger, server, args) else: Errors.exit_with_error( logger, message=_("tabcmd.get.extension.not_found"))
def run_command(args): logger = log(__class__.__name__, args.logging_level) logger.debug(_("tabcmd.launching")) session = Session() server = session.create_session(args) if args.parent_project_path is not None: project_path = Server.get_project_by_name_and_parent_path( logger, server, None, args.parent_project_path) else: project_path = None try: project = PublishSamplesCommand.get_project_by_name_and_parent_path( logger, server, args.project_name, project_path) except Exception as e: Errors.exit_with_error( logger, _("tabcmd.report.error.publish_samples.expected_project"), exception=e) try: server.projects.update(project, samples=True) except Exception as e: Errors.exit_with_error(logger, _("tabcmd.result.failure.publish_samples"), exception=e)
def _create_new_connection(self): self.logger.info(_("session.new_session")) self.tableau_server = self._set_connection_options() self._print_server_info() self.logger.info(_("session.connecting")) self.tableau_server.use_server_version( ) # this will attempt to contact the server
def validate_file_for_import(csv_file: io.TextIOWrapper, logger, detailed=False, strict=False) -> int: num_errors = 0 num_valid_lines = 0 csv_file.seek( 0) # set to start of file in case it has been read earlier line: str = csv_file.readline() while line and line != "": try: printable_line = line if detailed: # do not print passwords printable_line = line.split(",")[0] UserCommand._validate_user_or_throw(line, logger) else: logger.debug("> username - {}".format(line)) UserCommand._validate_username_or_throw(line) num_valid_lines += 1 except Exception as exc: logger.info( _("importcsvsummary.error.line").format( printable_line, exc, "")) num_errors += 1 line = csv_file.readline() if strict and num_errors > 0: Errors.exit_with_error(logger, _("importcsvsummary.error.too_many_errors")) return num_valid_lines
def _sign_in(self, tableau_auth): self.logger.debug(_("session.login") + self.server_url) self.logger.debug( _("listsites.output").format("", self.username or self.token_name, self.site_name)) try: self.tableau_server.auth.sign_in( tableau_auth) # it's the same call for token or user-pass except TSC.ServerResponseError as e: Errors.exit_with_error(self.logger, exception=e) try: self.site_id = self.tableau_server.site_id self.user_id = self.tableau_server.user_id self.auth_token = self.tableau_server._auth_token if not self.username: self.username = self.tableau_server.users.get_by_id( self.user_id).name self.logger.debug("Signed into {0}{1} as {2}".format( self.server_url, self.site_name, self.username)) self.logger.info(_("common.output.succeeded")) except TSC.ServerResponseError as e: Errors.exit_with_error( self.logger, _("publish.errors.unexpected_server_response"), e) return self.tableau_server
def run_command(args): logger = log(__class__.__name__, args.logging_level) logger.debug(_("tabcmd.launching")) session = Session() server = session.create_session(args) logger.info( _("tabcmd.add.users.to_site").format(args.users.name, args.name)) UserCommand.act_on_users(logger, server, "added", server.groups.add_user, args)
def _validate_username_or_throw(username) -> None: if username is None or username == "" or username.strip(" ") == "": raise AttributeError(_("user.input.name.err.empty")) if username.find(" ") >= 0: raise AttributeError( _("tabcmd.report.error.user.no_spaces_in_username")) at_symbol = username.find("@") if at_symbol >= 0: username = username[:at_symbol] + "X" + username[at_symbol + 1:] if username.find("@") >= 0: raise AttributeError(_("tabcmd.report.error.user_csv.at_char"))
def parse_export_url_to_workbook_and_view(logger, url): logger.info(_("export.status").format(url)) if " " in url: Errors.exit_with_error(logger, _("export.errors.white_space_workbook_view")) # input should be workbook_name/view_name if not url.find("/"): return None, None name_parts = url.split("/") if len(name_parts) != 2: return None, None workbook = name_parts[0] view = "{}/sheets/{}".format(workbook, name_parts[1]) return view, workbook
def run_command(args): logger = log(__class__.__name__, args.logging_level) logger.debug(_("tabcmd.launching")) session = Session() server = session.create_session(args) try: logger.info(_("tabcmd.find.group").format(args.name)) group_id = Server.find_group_id(logger, server, args.name) logger.info(_("deletegroup.status").format(group_id)) server.groups.delete(group_id) logger.info(_("tabcmd.result.succeeded")) except TSC.ServerResponseError as e: Errors.exit_with_error(logger, "tabcmd.result.failed.delete.group", e)
def run_command(args): logger = log(__class__.__name__, args.logging_level) logger.debug(_("tabcmd.launching")) session = Session() server = session.create_session(args) logger.info(_("export.status").format(args.schedule)) schedule = DatasourcesAndWorkbooks.get_items_by_name( logger, server.schedules, args.schedule)[0] if not schedule: Errors.exit_with_error( logger, _("publish.errors.server_resource_not_found")) logger.info(_("runschedule.status")) Errors.exit_with_error(logger, "Not yet implemented")
def _validate_existing_signin(self): self.logger.info(_("session.continuing_session")) self.tableau_server = self._set_connection_options() try: if self.tableau_server and self.tableau_server.is_signed_in(): response = self.tableau_server.users.get_by_id(self.user_id) self.logger.debug(response) if response.status_code.startswith("200"): return self.tableau_server except TSC.ServerResponseError as e: self.logger.info(_("publish.errors.unexpected_server_response"), e) except Exception as e: self.logger.info(_("errors.internal_error.request.message"), e) return None
def run_command(args): logger = log(__class__.__name__, args.logging_level) logger.debug(_("tabcmd.launching")) session = Session() server = session.create_session(args) site_item = Server.get_site_for_command_or_throw(logger, server, args) try: logger.info(_("reencryptextracts.status").format(site_item.name)) job = server.sites.encrypt_extracts(site_item.id) except TSC.ServerResponseError as e: Errors.exit_with_error(logger, e) logger.info(_("common.output.job_queued_success")) logger.debug("Extract re-encryption queued with JobID: {}".format(job.id))
def create_session(self, args): signed_in_object = None # pull out cached info from json, then overwrite with new args if available self._read_existing_state() self._update_session_data(args) self.logging_level = args.logging_level or self.logging_level credentials = None if args.password: self._end_session() # we don't save the password anywhere, so we pass it along directly credentials = self._create_new_credential( args.password, Session.PASSWORD_CRED_TYPE) elif args.password_file: self._end_session() if args.username: credentials = self._create_new_credential( args.password, Session.PASSWORD_CRED_TYPE) else: credentials = self._create_new_credential( args.password, Session.TOKEN_CRED_TYPE) elif args.token: self._end_session() credentials = self._create_new_token_credential() else: # no login arguments given - look for saved info # maybe we're already signed in! if self.tableau_server: signed_in_object = self._validate_existing_signin() self.logger.debug(signed_in_object) # or maybe we at least have the credentials saved if not signed_in_object: credentials = self._get_saved_credentials() if credentials and not signed_in_object: # logging in, not using an existing session self._create_new_connection() signed_in_object = self._sign_in(credentials) if not signed_in_object: missing_var = _("editdomain.errors.requires_nickname_name").format( "username", "token") Errors.exit_with_error( self.logger, _("session.errors.missing_arguments").format(missing_var)) if args.no_cookie: self._remove_json() else: self._save_session_to_json() return signed_in_object
def run_command(args): logger = log(__class__.__name__, args.logging_level) logger.debug(_("tabcmd.launching")) session = Session() server = session.create_session(args) try: logger.info(_("creategroup.status").format(args.name)) new_group = TSC.GroupItem(args.name) server.groups.create(new_group) logger.info(_("tabcmd.result.succeeded")) except TSC.ServerResponseError as e: if args.continue_if_exists and Errors.is_resource_conflict(e): logger.info(_("tabcmd.result.already_exists.group").format(args.name)) return Errors.exit_with_error(logger, "tabcmd.result.failed.create_group")
class CreateGroupCommand(Server): """ This command is used to create a group """ name: str = "creategroup" description: str = _("creategroup.short_description") @staticmethod def define_args(create_group_parser): create_group_parser.add_argument("name") @staticmethod def run_command(args): logger = log(__class__.__name__, args.logging_level) logger.debug(_("tabcmd.launching")) session = Session() server = session.create_session(args) try: logger.info(_("creategroup.status").format(args.name)) new_group = TSC.GroupItem(args.name) server.groups.create(new_group) logger.info(_("tabcmd.result.succeeded")) except TSC.ServerResponseError as e: if args.continue_if_exists and Errors.is_resource_conflict(e): logger.info(_("tabcmd.result.already_exists.group").format(args.name)) return Errors.exit_with_error(logger, "tabcmd.result.failed.create_group")
class AddUserCommand(UserCommand): """ Command to Adds users to a specified group """ name: str = "addusers" description: str = _("addusers.short_description") @staticmethod def define_args(add_user_parser): add_user_parser.add_argument("name", help="name of group to add users to") set_users_file_arg(add_user_parser) set_completeness_options(add_user_parser) @staticmethod def run_command(args): logger = log(__class__.__name__, args.logging_level) logger.debug(_("tabcmd.launching")) session = Session() server = session.create_session(args) logger.info( _("tabcmd.add.users.to_site").format(args.users.name, args.name)) UserCommand.act_on_users(logger, server, "added", server.groups.add_user, args)
class EncryptExtracts(Server): """ Command that encrypt all extracts on a site. If no site is specified, extracts on the default site will be encrypted. """ name: str = "encryptextracts" description: str = _("encryptextracts.short_description") @staticmethod def define_args(encrypt_extract_parser): encrypt_extract_parser.add_argument( "site_name", metavar="site-name", help=_("editsite.options.site-name")) @staticmethod def run_command(args): logger = log(__class__.__name__, args.logging_level) logger.debug(_("tabcmd.launching")) session = Session() server = session.create_session(args) site_item = Server.get_site_for_command_or_throw(logger, server, args) try: logger.info(_("encryptextracts.status").format(site_item.name)) job = server.sites.encrypt_extracts(site_item.id) except TSC.ServerResponseError as e: Errors.exit_with_error(logger, e) logger.info(_("common.output.job_queued_success")) logger.debug("Extract encryption queued with JobID: {}".format(job.id))
class RunSchedule(DatasourcesAndWorkbooks): """ This command runs the specified schedule as it is on the server. """ name: str = "runschedule" description: str = _("runschedule.short_description") @staticmethod def define_args(runschedule_parser): runschedule_parser.add_argument( "schedule", help=_("tabcmd.run_schedule.options.schedule")) @staticmethod def run_command(args): logger = log(__class__.__name__, args.logging_level) logger.debug(_("tabcmd.launching")) session = Session() server = session.create_session(args) logger.info(_("export.status").format(args.schedule)) schedule = DatasourcesAndWorkbooks.get_items_by_name( logger, server.schedules, args.schedule)[0] if not schedule: Errors.exit_with_error( logger, _("publish.errors.server_resource_not_found")) logger.info(_("runschedule.status")) Errors.exit_with_error(logger, "Not yet implemented")
def define_args(delete_extract_parser): set_ds_xor_wb_args(delete_extract_parser) set_embedded_datasources_options(delete_extract_parser) # set_encryption_option(delete_extract_parser) set_project_arg(delete_extract_parser) set_parent_project_arg(delete_extract_parser) delete_extract_parser.add_argument("--url", help=_("createextracts.options.url"))
class DeleteSiteCommand(Server): """ Command to delete a site """ name: str = "deletesite" description: str = _("deletesite.short_description") @staticmethod def define_args(delete_site_parser): delete_site_parser.add_argument("site_name", help="name of site to delete") @staticmethod def run_command(args): logger = log(__class__.__name__, args.logging_level) logger.debug(_("tabcmd.launching")) session = Session() server = session.create_session(args) site_id = server.sites.get_by_name(args.site_name) if site_id == session.site_id: Errors.exit_with_error( logger, "Cannot delete the site you are logged in to") try: server.sites.delete(site_id) logger.info("Successfully deleted the site") except TSC.ServerResponseError as e: Errors.exit_with_error(logger, "Error deleting site", e)
def run_command(args): logger = log(__class__.__name__, args.logging_level) logger.debug(_("tabcmd.launching")) session = Session() server = session.create_session(args) try: sites, pagination = server.sites.get() logger.info(_("listsites.status").format(session.username)) for site in sites: print("NAME:", site.name) print("SITEID:", site.content_url) if args.get_extract_encryption_mode: print("EXTRACTENCRYPTION:", site.extract_encryption_mode) print("") except TSC.ServerResponseError as e: Errors.exit_with_error(logger, e)
class DeleteGroupCommand(Server): """ This command deletes the specified group from the server """ name: str = "deletegroup" description: str = _("deletegroup.short_description") @staticmethod def define_args(delete_group_parser): delete_group_parser.add_argument("name") @staticmethod def run_command(args): logger = log(__class__.__name__, args.logging_level) logger.debug(_("tabcmd.launching")) session = Session() server = session.create_session(args) try: logger.info(_("tabcmd.find.group").format(args.name)) group_id = Server.find_group_id(logger, server, args.name) logger.info(_("deletegroup.status").format(group_id)) server.groups.delete(group_id) logger.info(_("tabcmd.result.succeeded")) except TSC.ServerResponseError as e: Errors.exit_with_error(logger, "tabcmd.result.failed.delete.group", e)
class ListSiteCommand(Server): """ Command to return a list of sites to which the logged in user belongs """ name: str = "listsites" description: str = _("listsites.short_description") @staticmethod def define_args(list_site_parser): set_view_site_encryption(list_site_parser) @staticmethod def run_command(args): logger = log(__class__.__name__, args.logging_level) logger.debug(_("tabcmd.launching")) session = Session() server = session.create_session(args) try: sites, pagination = server.sites.get() logger.info(_("listsites.status").format(session.username)) for site in sites: print("NAME:", site.name) print("SITEID:", site.content_url) if args.get_extract_encryption_mode: print("EXTRACTENCRYPTION:", site.extract_encryption_mode) print("") except TSC.ServerResponseError as e: Errors.exit_with_error(logger, e)
class ReencryptExtracts(Server): """ Command to Reencrypt all extracts on a site with new encryption keys. This command will regenerate the key encryption key and data encryption key. You must specify a site. """ name: str = "reencryptextracts" description: str = _("reencryptextracts.short_description=") @staticmethod def define_args(reencrypt_extract_parser): reencrypt_extract_parser.add_argument("site_name", metavar="site-name", help=_("editsite.options.site-name")) @staticmethod def run_command(args): logger = log(__class__.__name__, args.logging_level) logger.debug(_("tabcmd.launching")) session = Session() server = session.create_session(args) site_item = Server.get_site_for_command_or_throw(logger, server, args) try: logger.info(_("reencryptextracts.status").format(site_item.name)) job = server.sites.encrypt_extracts(site_item.id) except TSC.ServerResponseError as e: Errors.exit_with_error(logger, e) logger.info(_("common.output.job_queued_success")) logger.debug("Extract re-encryption queued with JobID: {}".format(job.id))
def get_view_by_content_url(logger, server, view_content_url) -> TSC.ViewItem: logger.debug(_("export.status").format(view_content_url)) try: req_option = TSC.RequestOptions() req_option.filter.add( TSC.Filter("contentUrl", TSC.RequestOptions.Operator.Equals, view_content_url)) matching_views, paging = server.views.get(req_option) except TSC.ServerResponseError as e: Errors.exit_with_error( logger, _("publish.errors.unexpected_server_response").format("")) if len(matching_views) < 1: Errors.exit_with_error(logger, message=_("errors.xmlapi.not_found")) return matching_views[0]
def get_wb_by_content_url(logger, server, workbook_content_url) -> TSC.WorkbookItem: logger.debug(_("export.status").format(workbook_content_url)) try: req_option = TSC.RequestOptions() req_option.filter.add( TSC.Filter("contentUrl", TSC.RequestOptions.Operator.Equals, workbook_content_url)) matching_workbooks, paging = server.workbooks.get(req_option) except TSC.ServerResponseError as e: Errors.exit_with_error( logger, _("publish.errors.unexpected_server_response").format("")) if len(matching_workbooks) < 1: Errors.exit_with_error( logger, message=_("dataalerts.failure.error.workbookNotFound")) return matching_workbooks[0]
def generate_png(logger, server, args): view = GetUrl.get_view_url(args.url) try: view_item: TSC.ViewItem = GetUrl.get_view_by_content_url( logger, server, view) logger.debug( _("content_type.view") + ": {}".format(view_item.name)) req_option_csv = TSC.CSVRequestOptions(maxage=1) server.views.populate_csv(view_item, req_option_csv) filename = GetUrl.filename_from_args(args.filename, view_item.name, "png") with open(filename, "wb") as f: f.write(view_item.png) logger.info(_("export.success").format(view_item.name, filename)) except TSC.ServerResponseError as e: GetUrl.exit_with_error( logger, _("publish.errors.unexpected_server_response"), e)