Ejemplo n.º 1
0
    def test_publish_multi_connection(self):
        new_datasource = TSC.DatasourceItem(
            name='Sample', project_id='ee8c6e70-43b6-11e6-af4f-f7b0d8e20760')
        connection1 = TSC.ConnectionItem()
        connection1.server_address = 'mysql.test.com'
        connection1.connection_credentials = TSC.ConnectionCredentials(
            'test', 'secret', True)
        connection2 = TSC.ConnectionItem()
        connection2.server_address = 'pgsql.test.com'
        connection2.connection_credentials = TSC.ConnectionCredentials(
            'test', 'secret', True)

        response = RequestFactory.Datasource._generate_xml(
            new_datasource, connections=[connection1, connection2])
        # Can't use ConnectionItem parser due to xml namespace problems
        connection_results = ET.fromstring(response).findall('.//connection')

        self.assertEqual(connection_results[0].get('serverAddress', None),
                         'mysql.test.com')
        self.assertEqual(
            connection_results[0].find('connectionCredentials').get(
                'name', None), 'test')
        self.assertEqual(connection_results[1].get('serverAddress', None),
                         'pgsql.test.com')
        self.assertEqual(
            connection_results[1].find('connectionCredentials').get(
                'password', None), 'secret')
    def test_publish_multi_connection(self) -> None:
        new_datasource = TSC.DatasourceItem(
            name="Sample", project_id="ee8c6e70-43b6-11e6-af4f-f7b0d8e20760")
        connection1 = TSC.ConnectionItem()
        connection1.server_address = "mysql.test.com"
        connection1.connection_credentials = TSC.ConnectionCredentials(
            "test", "secret", True)
        connection2 = TSC.ConnectionItem()
        connection2.server_address = "pgsql.test.com"
        connection2.connection_credentials = TSC.ConnectionCredentials(
            "test", "secret", True)

        response = RequestFactory.Datasource._generate_xml(
            new_datasource, connections=[connection1, connection2])
        # Can't use ConnectionItem parser due to xml namespace problems
        connection_results = fromstring(response).findall(".//connection")

        self.assertEqual(connection_results[0].get("serverAddress", None),
                         "mysql.test.com")
        self.assertEqual(
            connection_results[0].find("connectionCredentials").get(
                "name", None), "test")  # type: ignore[union-attr]
        self.assertEqual(connection_results[1].get("serverAddress", None),
                         "pgsql.test.com")
        self.assertEqual(
            connection_results[1].find("connectionCredentials").get(
                "password", None), "secret")  # type: ignore[union-attr]
Ejemplo n.º 3
0
    def test_credentials_and_multi_connect_raises_exception(self):
        new_datasource = TSC.DatasourceItem(name='Sample', project_id='ee8c6e70-43b6-11e6-af4f-f7b0d8e20760')

        connection_creds = TSC.ConnectionCredentials('test', 'secret', True)

        connection1 = TSC.ConnectionItem()
        connection1.server_address = 'mysql.test.com'
        connection1.connection_credentials = TSC.ConnectionCredentials('test', 'secret', True)

        with self.assertRaises(RuntimeError):
            response = RequestFactory.Datasource._generate_xml(new_datasource,
                                                               connection_credentials=connection_creds,
                                                               connections=[connection1])
Ejemplo n.º 4
0
    def test_credentials_and_multi_connect_raises_exception(self) -> None:
        new_workbook = TSC.WorkbookItem(
            name="Sample", show_tabs=False, project_id="ee8c6e70-43b6-11e6-af4f-f7b0d8e20760"
        )

        connection_creds = TSC.ConnectionCredentials("test", "secret", True)

        connection1 = TSC.ConnectionItem()
        connection1.server_address = "mysql.test.com"
        connection1.connection_credentials = TSC.ConnectionCredentials("test", "secret", True)

        with self.assertRaises(RuntimeError):
            response = RequestFactory.Workbook._generate_xml(
                new_workbook, connection_credentials=connection_creds, connections=[connection1]
            )
Ejemplo n.º 5
0
def publishDataSource(filePath, projectId):
    tableauAuth = TSC.TableauAuth(tableauUserId, tableauPassword)
    server = TSC.Server(tableauServerAddress)

    if tableauIgnoreSslCert:
        server.add_http_options({'verify': False})

    server.auth.sign_in(tableauAuth)

    datasourceCredentials = TSC.ConnectionCredentials(name=pgUser,
                                                      password=pgPassword)

    datasource = TSC.DatasourceItem(projectId)

    if useCustomSQL:
        datasource.name = dataSourceName

    datasource = server.datasources.publish(datasource, filePath, 'CreateNew',
                                            datasourceCredentials)

    if verbose:
        print('Published datasource {} to Tableau Server running at {}'.format(
            datasource.name, tableauServerAddress))
        lineClear()

    server.auth.sign_out()
Ejemplo n.º 6
0
def migrate_datasource(datasource, input="in", output="out"):
    try:
        os.mkdir(os.path.join(ipath, datasource.project_id))
    except:
        pass
    tdsx = os.path.join(ipath, datasource.project_id, datasource.id + '.tdsx')
    print("datasource: {} > {}".format(datasource.name, tdsx))
    datasource.project_id = pmap[datasource.project_id]
    tableau_servers[input]["server"].datasources.download(datasource.id,
                                                          filepath=tdsx)
    print('patching {} to output server'.format(tdsx))
    updateTDSX(tdsx, input, output)
    tableau_servers[input]["server"].datasources.populate_connections(
        datasource)
    cc = TSC.ConnectionCredentials(
        datasource.connections[0].username,
        passwords[datasource.connections[0].username],
        embed=True,
        oauth=False)
    in_id = datasource.id
    out_id = tableau_servers[output]["server"].datasources.publish(
        datasource,
        tdsx,
        TSC.Server.PublishMode.Overwrite,
        connection_credentials=cc).id
    dmap[in_id] = out_id
Ejemplo n.º 7
0
 def test_generate_xml_valid_connection_credentials(self):
     workbook_item: TSC.WorkbookItem = TSC.WorkbookItem(
         "name", "project_id")
     conn = TSC.ConnectionItem()
     conn.server_address = "address"
     creds = TSC.ConnectionCredentials("username", "DELETEME")
     conn.connection_credentials = creds
     request = TSC_RF.RequestFactory.Workbook._generate_xml(
         workbook_item, connections=[conn])
     assert request.find(b"DELETEME") > 0
Ejemplo n.º 8
0
 def test_generate_xml_invalid_connection_credentials(self):
     workbook_item: TSC.WorkbookItem = TSC.WorkbookItem(
         "name", "project_id")
     conn = TSC.ConnectionItem()
     conn.server_address = "address"
     creds = TSC.ConnectionCredentials("username", "password")
     creds.name = None
     conn.connection_credentials = creds
     with self.assertRaises(ValueError):
         request = TSC_RF.RequestFactory.Workbook._generate_xml(
             workbook_item, connections=[conn])
Ejemplo n.º 9
0
    def test_publish_single_connection(self):
        new_workbook = TSC.WorkbookItem(name='Sample', show_tabs=False,
                                        project_id='ee8c6e70-43b6-11e6-af4f-f7b0d8e20760')
        connection_creds = TSC.ConnectionCredentials('test', 'secret', True)

        response = RequestFactory.Workbook._generate_xml(new_workbook, connection_credentials=connection_creds)
        # Can't use ConnectionItem parser due to xml namespace problems
        credentials = ET.fromstring(response).findall('.//connectionCredentials')
        self.assertEqual(len(credentials), 1)
        self.assertEqual(credentials[0].get('name', None), 'test')
        self.assertEqual(credentials[0].get('password', None), 'secret')
        self.assertEqual(credentials[0].get('embed', None), 'true')
Ejemplo n.º 10
0
    def test_publish_single_connection(self) -> None:
        new_workbook = TSC.WorkbookItem(
            name="Sample", show_tabs=False, project_id="ee8c6e70-43b6-11e6-af4f-f7b0d8e20760"
        )
        connection_creds = TSC.ConnectionCredentials("test", "secret", True)

        response = RequestFactory.Workbook._generate_xml(new_workbook, connection_credentials=connection_creds)
        # Can't use ConnectionItem parser due to xml namespace problems
        credentials = fromstring(response).findall(".//connectionCredentials")
        self.assertEqual(len(credentials), 1)
        self.assertEqual(credentials[0].get("name", None), "test")
        self.assertEqual(credentials[0].get("password", None), "secret")
        self.assertEqual(credentials[0].get("embed", None), "true")
Ejemplo n.º 11
0
 def test_redact_passwords_in_xml(self):
     if sys.version_info < (3, 7):
         pytest.skip("Redaction is only implemented for 3.7+.")
     workbook_item: TSC.WorkbookItem = TSC.WorkbookItem(
         "name", "project_id")
     conn = TSC.ConnectionItem()
     conn.server_address = "address"
     creds = TSC.ConnectionCredentials("username", "DELETEME")
     conn.connection_credentials = creds
     request = TSC_RF.RequestFactory.Workbook._generate_xml(
         workbook_item, connections=[conn])
     redacted = redact_xml(request)
     assert request.find(b"DELETEME") > 0, request
     assert redacted.find(b"DELETEME") == -1, redacted
Ejemplo n.º 12
0
def publish_hyper(hyper_file, credential_path, flow_path=None, **kwargs):
    """ publishes local extract.hyper file to tableau server, main method is datasources.publish(datasource_item, file_path, mode, connection_credentials=None)
    https://tableau.github.io/server-client-python/docs/api-ref#data-sources

    Arguments:
        hyper_file {str} -- filepath of extract.hyper or .tde to be published
        credential_path {str} -- credential.json file per tableau prep cli specification, must contain `outputConnections` credentails for Tableau server

    Keyword Arguments:
        project {str} -- tableau server folder/project where to publish (Defaults: {Defaults})
        mode {str} -- publish mode CreateNew|Overwrite|Append (Defaults: Overwrite)
        embed {bool} -- if True, embeds credentails in data source (Defaults: True)
        flow_path {str} -- flow file path for infering extract.hyper path and name (default: {None})
        name {str} -- name of extract file on server to be replaced or appended to
    """
    with open(credential_path, 'r') as file:
        credentials = json.load(file).get('outputConnections')[0]
    server_address = credentials.get('serverUrl')
    username = credentials.get('username')
    password = credentials.get('password')
    logging.info(f"singing into {server_address} as {username}")

    server = TSC.Server(server_address)
    tableau_auth = TSC.TableauAuth(
        username, password, credentials.get('contentUrl'))
    # server.auth.sign_in(tableau_auth)

    logging.debug(f'supplied keyword args: {kwargs}')
    with server.auth.sign_in(tableau_auth):
        assert server.is_signed_in() == True
        if 'project' in kwargs.keys():
            project = kwargs.get('project')
        else:
            project = 'Default'

        all_project_items, pagination_item = server.projects.get()
        try:
            project_id = [
                item.id for item in all_project_items if item.name == project][0]
        except:
            project_id = [
                item.id for item in all_project_items if item.name == 'Default'][0]

        logging.debug(f"project_id for {project} is : {project_id}")

        if not hyper_file:
            if flow_path:
                flow_name = os.path.basename(flow_path)
                project_dir = os.path.dirname(flow_path)
                os.chdir(project_dir)
                hyper_list = get_files_in_folder(
                    folderpath=project_dir, file_extenion="hyper")
                if len(hyper_list) > 1:
                    name = hyper_list[0]
                    logging.warning(
                        f'found more that one hyper files in tableau prep flow folder ``{project_dir}``, publising ``{name}`` to server. explicitly provide hyper_path to publish desired extract file')
                elif len(hyper_list) == 1:
                    name = hyper_list[0]
                else:
                    logging.error(
                        f'no extract.hyper file was found in tableau prep flow folder ``{project_dir}``, check that flow outputs file in hyper format or explicitly provide hyper_path to publish desired extract file')
            else:
                logging.error(
                    f'could not find extract.hyper file to publish, explicitly provide hyper_path to publish desired extract file')
            hyper_filepath = os.path.join(project_dir, name)
        elif os.path.isfile(hyper_file) == True:
            hyper_filepath = hyper_file
            name = os.path.basename(hyper_file)
        else:  # when only filename is passed which is in project folder
            name = hyper_file
            hyper_filepath = os.path.join(project_dir, name)

        assert os.path.isfile(hyper_filepath) == True
        logging.debug(
            f'publishing extract file ``{hyper_filepath}`` to ``{project}`` project')
        name = name.split('.')[0]  # remove file extension

        if 'mode' in kwargs.keys():
            mode = kwargs.get('mode').title()
            if mode == 'Createnew':
                mode = 'CreateNew'

            if mode == 'Append':
                all_datasources, pagination_item = server.datasources.get()
                if 'name' in kwargs.keys():
                    name = kwargs.get('name')
                datasource_id = [
                    datasource.id for datasource in all_datasources if datasource.name == name][0]
                data_source_item = server.datasources.get_by_id(datasource_id)
                logging.debug(f"appending {hyper_filepath} to {name}")
            else:
                data_source_item = TSC.DatasourceItem(
                    project_id=project_id, name=name)
                logging.debug(
                    f"publishing {hyper_filepath} as {name} in {mode} mode")

        else:
            mode = 'Overwrite'
            data_source_item = TSC.DatasourceItem(
                project_id=project_id, name=name)

        logging.debug(
            f"publishing {hyper_filepath} as ``{name}`` in {mode} mode to ``{server_address}`` in ``{project}`` project")
        if 'embed' in kwargs.keys():
            embedded_credential = TSC.ConnectionCredentials(
                username, password, embed=embed, oauth=False)
            server.datasources.publish(
                data_source_item, hyper_filepath, mode, connection_credentials=embedded_credential)
        else:
            server.datasources.publish(
                data_source_item, hyper_filepath, mode)
    logging.info(f'{hyper_filepath} was successfully published in {mode} mode to {project} project!'))
Ejemplo n.º 13
0
        with server.auth.sign_in(tableau_auth):
            user = TSC.UserItem(server_username[i], 'SiteAdministrator')
            user = server.users.add(user)
            user = server.users.update(user, 'password')

#Getting the default project and publishing workbook and datasource###
    project_id = ''
    time.sleep(1)
    with server.auth.sign_in(tableau_auth):
        all_projects, pagination_item = server.projects.get()
        for project in all_projects:

            if project.name == 'Default':
                project_id = project.id

    new_workbook = TSC.WorkbookItem(project_id)
    new_datasource = TSC.DatasourceItem(project_id)
    credentials = TSC.ConnectionCredentials(db_username[i],
                                            db_password[i],
                                            embed=True)

    with server.auth.sign_in(tableau_auth):
        server.datasources.publish(new_datasource, uniqueField[i] + ".tdsx",
                                   TSC.Server.PublishMode.Overwrite,
                                   credentials)
        server.workbooks.publish(new_workbook, uniqueField[i] + ".twbx",
                                 TSC.Server.PublishMode.Overwrite, credentials)

    site_check = 0

# print "The workbook connections have been updated. Please open the newly created workbook to test."
Ejemplo n.º 14
0
import tableauserverclient as TSC
import config
import os
import pandas as pd

auth = config.TableauAuth
cred = config.Credentials

#Import of credentials and logins from config file

server = TSC.Server(auth["server"], use_server_version=True)
credentials = TSC.ConnectionCredentials(cred["user"], cred["password"], embed=True)

def sign_in(site_id, option):
    if option == True:
        tableau_auth = TSC.TableauAuth(auth["username"], auth["password"], site_id)
        server.auth.sign_in(tableau_auth)
        #Signs into the site using the tableau authentification information
    else: server.auth.sign_out()

class server_con():
    def __init__(self, site, type, name):
        self.site = site
        self.projs = list(TSC.Pager(server.projects, TSC.RequestOptions(pagenumber=1)))
        self.type = type
        self.name = name

        request_options = TSC.RequestOptions(pagenumber=1)
        if type == "ds":
            self.item_list = list(TSC.Pager(server.datasources, request_options)) #Gets list of datasource items in site
        elif type =="wb":
def main():
    parser = argparse.ArgumentParser(
        description="Publish a datasource to server.")
    # Common options; please keep those in sync across all samples
    parser.add_argument("--server", "-s", required=True, help="server address")
    parser.add_argument("--site", "-S", help="site name")
    parser.add_argument(
        "--token-name",
        "-p",
        required=True,
        help="name of the personal access token used to sign into the server")
    parser.add_argument(
        "--token-value",
        "-v",
        required=True,
        help="value of the personal access token used to sign into the server")
    parser.add_argument(
        "--logging-level",
        "-l",
        choices=["debug", "info", "error"],
        default="error",
        help="desired logging level (set to error by default)",
    )
    # Options specific to this sample
    parser.add_argument("--file",
                        "-f",
                        required=True,
                        help="filepath to the datasource to publish")
    parser.add_argument("--project",
                        help="Project within which to publish the datasource")
    parser.add_argument("--async",
                        "-a",
                        help="Publishing asynchronously",
                        dest="async_",
                        action="store_true")
    parser.add_argument("--conn-username", help="connection username")
    parser.add_argument("--conn-password", help="connection password")
    parser.add_argument("--conn-embed",
                        help="embed connection password to datasource",
                        action="store_true")
    parser.add_argument("--conn-oauth",
                        help="connection is configured to use oAuth",
                        action="store_true")

    args = parser.parse_args()

    # Ensure that both the connection username and password are provided, or none at all
    if (args.conn_username
            and not args.conn_password) or (not args.conn_username
                                            and args.conn_password):
        parser.error(
            "Both the connection username and password must be provided")

    # Set logging level based on user input, or error by default
    logging_level = getattr(logging, args.logging_level.upper())
    logging.basicConfig(level=logging_level)

    # Sign in to server
    tableau_auth = TSC.PersonalAccessTokenAuth(args.token_name,
                                               args.token_value,
                                               site_id=args.site)
    server = TSC.Server(args.server, use_server_version=True)
    with server.auth.sign_in(tableau_auth):
        # Empty project_id field will default the publish to the site's default project
        project_id = ""

        # Retrieve the project id, if a project name was passed
        if args.project is not None:
            req_options = TSC.RequestOptions()
            req_options.filter.add(
                TSC.Filter(TSC.RequestOptions.Field.Name,
                           TSC.RequestOptions.Operator.Equals, args.project))
            projects = list(TSC.Pager(server.projects, req_options))
            if len(projects) > 1:
                raise ValueError("The project name is not unique")
            project_id = projects[0].id

        # Create a new datasource item to publish
        new_datasource = TSC.DatasourceItem(project_id=project_id)

        # Create a connection_credentials item if connection details are provided
        new_conn_creds = None
        if args.conn_username:
            new_conn_creds = TSC.ConnectionCredentials(args.conn_username,
                                                       args.conn_password,
                                                       embed=args.conn_embed,
                                                       oauth=args.conn_oauth)

        # Define publish mode - Overwrite, Append, or CreateNew
        publish_mode = TSC.Server.PublishMode.Overwrite

        # Publish datasource
        if args.async_:
            # Async publishing, returns a job_item
            new_job = server.datasources.publish(
                new_datasource,
                args.filepath,
                publish_mode,
                connection_credentials=new_conn_creds,
                as_job=True)
            print("Datasource published asynchronously. Job ID: {0}".format(
                new_job.id))
        else:
            # Normal publishing, returns a datasource_item
            new_datasource = server.datasources.publish(
                new_datasource,
                args.filepath,
                publish_mode,
                connection_credentials=new_conn_creds)
            print("Datasource published. Datasource ID: {0}".format(
                new_datasource.id))
Ejemplo n.º 16
0
def main():
    parser = argparse.ArgumentParser(
        description='Publish a datasource to server.')
    parser.add_argument('--server', '-s', required=True, help='server address')
    parser.add_argument('--site', '-i', help='site name')
    parser.add_argument(
        '--token-name',
        '-p',
        required=True,
        help='name of the personal access token used to sign into the server')
    parser.add_argument(
        '--token-value',
        '-v',
        required=True,
        help='value of the personal access token used to sign into the server')
    parser.add_argument('--filepath',
                        '-f',
                        required=True,
                        help='filepath to the datasource to publish')
    parser.add_argument('--logging-level',
                        '-l',
                        choices=['debug', 'info', 'error'],
                        default='error',
                        help='desired logging level (set to error by default)')
    parser.add_argument('--async',
                        '-a',
                        help='Publishing asynchronously',
                        dest='async_',
                        action='store_true')
    parser.add_argument('--conn-username', help='connection username')
    parser.add_argument('--conn-password', help='connection password')
    parser.add_argument('--conn-embed',
                        help='embed connection password to datasource',
                        action='store_true')
    parser.add_argument('--conn-oauth',
                        help='connection is configured to use oAuth',
                        action='store_true')

    args = parser.parse_args()

    # Ensure that both the connection username and password are provided, or none at all
    if (args.conn_username
            and not args.conn_password) or (not args.conn_username
                                            and args.conn_password):
        parser.error(
            "Both the connection username and password must be provided")

    # Set logging level based on user input, or error by default
    logging_level = getattr(logging, args.logging_level.upper())
    logging.basicConfig(level=logging_level)

    # Sign in to server
    tableau_auth = TSC.PersonalAccessTokenAuth(args.token_name,
                                               args.token_value,
                                               site_id=args.site)
    server = TSC.Server(args.server, use_server_version=True)
    with server.auth.sign_in(tableau_auth):
        # Create a new datasource item to publish - empty project_id field
        # will default the publish to the site's default project
        new_datasource = TSC.DatasourceItem(project_id="")

        # Create a connection_credentials item if connection details are provided
        new_conn_creds = None
        if args.conn_username:
            new_conn_creds = TSC.ConnectionCredentials(args.conn_username,
                                                       args.conn_password,
                                                       embed=args.conn_embed,
                                                       oauth=args.conn_oauth)

        # Define publish mode - Overwrite, Append, or CreateNew
        publish_mode = TSC.Server.PublishMode.Overwrite

        # Publish datasource
        if args.async_:
            # Async publishing, returns a job_item
            new_job = server.datasources.publish(
                new_datasource,
                args.filepath,
                publish_mode,
                connection_credentials=new_conn_creds,
                as_job=True)
            print("Datasource published asynchronously. Job ID: {0}".format(
                new_job.id))
        else:
            # Normal publishing, returns a datasource_item
            new_datasource = server.datasources.publish(
                new_datasource,
                args.filepath,
                publish_mode,
                connection_credentials=new_conn_creds)
            print("Datasource published. Datasource ID: {0}".format(
                new_datasource.id))