Ejemplo n.º 1
0
    def test_filter_sort_legacy(self):
        self.server.version = "3.6"
        with requests_mock.mock() as m:
            m.get(requests_mock.ANY)
            url = self.baseurl + "/views?queryParamExists=true"
            opts = TSC.RequestOptions()

            opts.filter.add(
                TSC.Filter(TSC.RequestOptions.Field.Tags,
                           TSC.RequestOptions.Operator.In,
                           ['stocks', 'market']))
            opts.sort.add(
                TSC.Sort(TSC.RequestOptions.Field.Name,
                         TSC.RequestOptions.Direction.Asc))

            resp = self.server.workbooks.get_request(url, request_object=opts)
            self.assertTrue(
                re.search('queryparamexists=true', resp.request.query))
            self.assertTrue(
                re.search('filter=tags:in:%5bstocks,market%5d',
                          resp.request.query))
            self.assertTrue(re.search('sort=name:asc', resp.request.query))
Ejemplo n.º 2
0
    def test_filter_in(self):
        with requests_mock.mock() as m:
            m.get(requests_mock.ANY)
            url = "http://test/api/2.3/sites/dad65087-b08b-4603-af4e-2887b8aafc67/workbooks"
            opts = TSC.RequestOptions(pagesize=13, pagenumber=13)

            opts.filter.add(
                TSC.Filter(TSC.RequestOptions.Field.Tags,
                           TSC.RequestOptions.Operator.In,
                           ['stocks', 'market']))

            resp = self.server.workbooks._make_request(
                requests.get,
                url,
                content=None,
                request_object=opts,
                auth_token='j80k54ll2lfMZ0tv97mlPvvSCRyD0DOM',
                content_type='text/xml')

            self.assertEqual(
                resp.request.query,
                'pagenumber=13&pagesize=13&filter=tags:in:[stocks,market]')
 def test_multiple_filter_options(self):
     with open(FILTER_MULTIPLE, 'rb') as f:
         response_xml = f.read().decode('utf-8')
     # To ensure that this is deterministic, run this a few times
     with requests_mock.mock() as m:
         # Sometimes pep8 requires you to do things you might not otherwise do
         url = ''.join(
             (self.baseurl, '/workbooks?pageNumber=1&pageSize=100&',
              'filter=name:eq:foo,tags:in:[sample,safari,weather]'))
         m.get(url, text=response_xml)
         req_option = TSC.RequestOptions()
         req_option.filter.add(
             TSC.Filter(TSC.RequestOptions.Field.Tags,
                        TSC.RequestOptions.Operator.In,
                        ['sample', 'safari', 'weather']))
         req_option.filter.add(
             TSC.Filter(TSC.RequestOptions.Field.Name,
                        TSC.RequestOptions.Operator.Equals, 'foo'))
         for _ in range(100):
             matching_workbooks, pagination_item = self.server.workbooks.get(
                 req_option)
             self.assertEqual(3, pagination_item.total_available)
    def test_double_query_params(self):
        with requests_mock.mock() as m:
            m.get(requests_mock.ANY)
            url = "http://test/api/2.3/sites/12345/views?queryParamExists=true"
            opts = TSC.RequestOptions()

            opts.filter.add(
                TSC.Filter(TSC.RequestOptions.Field.Tags,
                           TSC.RequestOptions.Operator.In,
                           ['stocks', 'market']))

            resp = self.server.workbooks._make_request(
                requests.get,
                url,
                content=None,
                request_object=opts,
                auth_token='j80k54ll2lfMZ0tv97mlPvvSCRyD0DOM',
                content_type='text/xml')
            self.assertTrue(
                re.search('queryparamexists=true', resp.request.query))
            self.assertTrue(
                re.search('filter=tags%3ain%3a%5bstocks%2cmarket%5d',
                          resp.request.query))
Ejemplo n.º 5
0
    def test_filter_combo(self):
        with requests_mock.mock() as m:
            m.get(requests_mock.ANY)
            url = "http://test/api/2.3/sites/dad65087-b08b-4603-af4e-2887b8aafc67/users"
            opts = TSC.RequestOptions(pagesize=13, pagenumber=13)

            opts.filter.add(TSC.Filter(TSC.RequestOptions.Field.LastLogin,
                                       TSC.RequestOptions.Operator.GreaterThanOrEqual,
                                       '2017-01-15T00:00:00:00Z'))

            opts.filter.add(TSC.Filter(TSC.RequestOptions.Field.SiteRole,
                                       TSC.RequestOptions.Operator.Equals,
                                       'Publisher'))

            resp = self.server.workbooks._make_request(requests.get,
                                                       url,
                                                       content=None,
                                                       request_object=opts,
                                                       auth_token='j80k54ll2lfMZ0tv97mlPvvSCRyD0DOM',
                                                       content_type='text/xml')

            expected = 'pagenumber=13&pagesize=13&filter=lastlogin:gte:2017-01-15t00:00:00:00z,siterole:eq:publisher'

            self.assertEqual(resp.request.query, expected)
def update_workbooks_by_paths(all_projects, materialized_views_config, server,
                              workbook_path_mapping):
    for workbook_name, workbook_paths in workbook_path_mapping.items():
        req_option = TSC.RequestOptions()
        req_option.filter.add(
            TSC.Filter(TSC.RequestOptions.Field.Name,
                       TSC.RequestOptions.Operator.Equals, workbook_name))
        workbooks = list(TSC.Pager(server.workbooks, req_option))
        all_paths = set(workbook_paths[:])
        for workbook in workbooks:
            path = find_project_path(all_projects[workbook.project_id],
                                     all_projects, "")
            if path in workbook_paths:
                all_paths.remove(path)
                workbook.materialized_views_config = materialized_views_config
                server.workbooks.update(workbook)
                print("Updated materialized views settings for workbook: {}".
                      format(path + '/' + workbook.name))

        for path in all_paths:
            print(
                "Cannot find workbook path: {}, each line should only contain one workbook path"
                .format(path + '/' + workbook_name))
    print('\n')
Ejemplo n.º 7
0
import logging
import json
import time
import datetime
import tableauserverclient as TSC

from DownloadConfiguration import *

start_time = time.time()
tableau_auth = TSC.TableauAuth(USER, PASSWORD, site_id=SITENAME)
server = TSC.Server(SERVER)
starttimestamp = datetime.datetime.now()
start_time = time.time()
fldrmonth = starttimestamp.strftime("%m")
fldryear = starttimestamp.strftime("%Y")
paging_options = TSC.RequestOptions(pagesize=1000)


def create_folders(parentfoldername, subfolder1=None, subfolder2=None):
    osparentfolder = "\\" + parentfoldername + "\\"
    if subfolder1 is None:
        ossubfolder1 = ""
    else:
        ossubfolder1 = "\\" + subfolder1 + "\\"
    if subfolder2 is None:
        ossubfolder2 = ""
    else:
        ossubfolder2 = "\\" + subfolder2 + "\\"
    if not os.path.exists(MAINFOLDER + osparentfolder + ossubfolder1 +
                          ossubfolder2):
        os.makedirs(MAINFOLDER + osparentfolder + ossubfolder1 + ossubfolder2)
def main():

    parser = argparse.ArgumentParser(
        description="Move one workbook from the"
        "default project of the default site to"
        "the default project of another site."
    )
    # 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("--workbook-name", "-w", required=True, help="name of workbook to move")
    parser.add_argument("--destination-site", "-d", required=True, help="name of site to move workbook into")

    args = parser.parse_args()

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

    # Step 1: Sign in to both sites on server
    tableau_auth = TSC.PersonalAccessTokenAuth(args.token_name, args.token_value, site_id=args.site)

    source_server = TSC.Server(args.server)
    dest_server = TSC.Server(args.server)

    with source_server.auth.sign_in(tableau_auth):
        # Step 2: Query workbook to move
        req_option = TSC.RequestOptions()
        req_option.filter.add(
            TSC.Filter(TSC.RequestOptions.Field.Name, TSC.RequestOptions.Operator.Equals, args.workbook_name)
        )
        all_workbooks, pagination_item = source_server.workbooks.get(req_option)

        # Step 3: Download workbook to a temp directory
        if len(all_workbooks) == 0:
            print("No workbook named {} found.".format(args.workbook_name))
        else:
            tmpdir = tempfile.mkdtemp()
            try:
                workbook_path = source_server.workbooks.download(all_workbooks[0].id, tmpdir)

                # Step 4: Check if destination site exists, then sign in to the site
                all_sites, pagination_info = source_server.sites.get()
                found_destination_site = any(
                    (True for site in all_sites if args.destination_site.lower() == site.content_url.lower())
                )
                if not found_destination_site:
                    error = "No site named {} found.".format(args.destination_site)
                    raise LookupError(error)

                tableau_auth.site_id = args.destination_site

                # Signing into another site requires another server object
                # because of the different auth token and site ID.
                with dest_server.auth.sign_in(tableau_auth):

                    # Step 5: Create a new workbook item and publish workbook. Note that
                    # an empty project_id will publish to the 'Default' project.
                    new_workbook = TSC.WorkbookItem(name=args.workbook_name, project_id="")
                    new_workbook = dest_server.workbooks.publish(
                        new_workbook, workbook_path, mode=TSC.Server.PublishMode.Overwrite
                    )
                    print("Successfully moved {0} ({1})".format(new_workbook.name, new_workbook.id))

                # Step 6: Delete workbook from source site and delete temp directory
                source_server.workbooks.delete(all_workbooks[0].id)

            finally:
                shutil.rmtree(tmpdir)
Ejemplo n.º 9
0
def main():

    try:
        tableauPassword = getCreds()

        logger.info('Preparing Backup')

        #setting up tableau login credentials
        tableau_auth = TSC.TableauAuth(cfg['tableauServer']['user'],
                                       tableauPassword)

        server = TSC.Server(cfg['tableauServer']['url'])
        server.add_http_options({'verify': False})
        server.use_server_version()

        firstTime = False

        #check if there is git repo, if not clone the repository
        oPath = cfg['git']['projectName']

        if os.path.isdir(oPath) is False:
            Repo.clone_from(cfg['git']['url'], oPath)
            firstTime = True

        repo = git.Repo(oPath)

        #logging into tableau server
        server.auth.sign_in(tableau_auth)

        #setting time stamp for one hour previous from when this script is run
        utc_value = int(cfg['tableauServer']['utc_value'])
        currentTime = datetime.now()

        if firstTime is True or args.full_load == True:
            downloadChangesSince = '2000-01-01T00:00:00Z'
        else:
            downloadChangesSince = (datetime.fromtimestamp(
                (currentTime.timestamp() -
                 (utc_value + args.incremental) * 3600)).replace(
                     microsecond=0)).isoformat() + 'Z'

        logger.info("downloadChangesSince: {0}".format(downloadChangesSince))

        req_option = TSC.RequestOptions()
        req_option.filter.add(
            TSC.Filter(TSC.RequestOptions.Field.UpdatedAt,
                       TSC.RequestOptions.Operator.GreaterThanOrEqual,
                       downloadChangesSince))

        remove_punctuation_and_turkish_map = dict(
            (ord(char), None) for char in '\/*?:"<>|')
        turkish_character_set = {
            ('ı', 'i'), ('İ', 'I'), ('ü', 'u'), ('Ü', 'U'), ('ö', 'o'),
            ('Ö', 'O'), ('ç', 'c'), ('Ç', 'C'), ('ş', 's'), ('Ş', 'S'),
            ('ğ', 'g'), ('Ğ', 'G')
        }
        for map_item in turkish_character_set:
            remove_punctuation_and_turkish_map.update(
                {ord(map_item[0]): map_item[1]})

        #iterating through each site on tableau
        for site in TSC.Pager(server.sites):

            logger.info(
                'Backing up workbooks and datasources under the {} site changed after {}'
                .format(site.name, downloadChangesSince))

            #logging into the specific site
            tableau_auth1 = TSC.TableauAuth(cfg['tableauServer']['user'],
                                            tableauPassword,
                                            site_id=site.content_url)
            server.auth.sign_in(tableau_auth1)

            sPath = os.path.join(
                oPath, site.name.translate(remove_punctuation_and_turkish_map))
            if os.path.isdir(sPath) is False:
                os.makedirs(sPath)

            #iterating through each workbook in the specified site to download and extract
            for workbook in TSC.Pager(server.workbooks, req_option):

                projectName = workbook.project_name.translate(
                    remove_punctuation_and_turkish_map)
                xPath = os.path.join(sPath, projectName)
                workbookFileName = os.path.join(
                    xPath,
                    workbook.name.translate(
                        remove_punctuation_and_turkish_map)) + '.twb'

                if os.path.isdir(xPath) is False:
                    os.makedirs(xPath)

                file_path = server.workbooks.download(
                    workbook.id, filepath=workbookFileName)

                #extractWorkbook(file_path, site.name, projectName, workbook.project_id, workbook.id, os.path.basename(file_path), xPath)

            #iterating through each datasource in the specified site to downlad and extract
            for datasources in TSC.Pager(server.datasources, req_option):

                projectName = datasources.project_name.translate(
                    remove_punctuation_and_turkish_map)
                dPath = os.path.join(sPath, projectName)
                datasourceFileName = os.path.join(
                    dPath,
                    datasources.name.translate(
                        remove_punctuation_and_turkish_map)) + ".tdsx"

                if os.path.isdir(dPath) is False:
                    os.makedirs(dPath)

                file_path = server.datasources.download(
                    datasources.id,
                    filepath=datasourceFileName,
                    include_extract=False)
                extractDatasource(file_path, site.name, projectName,
                                  datasources.project_id, datasources.id,
                                  os.path.basename(file_path), dPath)

        #pushing changes to git and timestamping when this script was run
        if "nothing to commit" not in repo.git.status():
            repo.git.add('.')
            repo.git.commit(m="last backup: " +
                            currentTime.strftime('%Y-%m-%d %H-%M-%S'))
            repo.git.push('origin')

        logger.info('Backup Complete')
        server.auth.sign_out()

    except:
        logging.exception('error')
        pass
Ejemplo n.º 10
0
class TableauServerCommunicator:
    req_opts = tsc.RequestOptions(pagesize=1000)
    tableau_server = None
    locale = None

    def __init__(self, in_language):
        file_parts = os.path.normpath(os.path.abspath(__file__)).replace('\\', os.path.altsep)\
            .split(os.path.altsep)
        locale_domain = file_parts[(len(file_parts) - 1)].replace('.py', '')
        locale_folder = os.path.normpath(
            os.path.join(
                os.path.join(os.path.altsep.join(file_parts[:-2]),
                             'project_locale'), locale_domain))
        self.locale = gettext.translation(locale_domain,
                                          localedir=locale_folder,
                                          languages=[in_language],
                                          fallback=True)

    def connect_to_tableau_server(self, local_logger, timer, in_connection):
        timer.start()
        local_logger.debug(
            self.locale.gettext(
                'About to connect to the Tableau Server with URL: {tableau_server}, '
                + 'Site {tableau_site} with Username = {user_name}').replace(
                    '{tableau_server}',
                    in_connection['Tableau Server']).replace(
                        '{tableau_site}',
                        in_connection['Tableau Site']).replace(
                            '{user_name}', in_connection['Username']))
        self.tableau_server = tsc.Server(in_connection['Tableau Server'], True)
        tableau_auth = tsc.TableauAuth(in_connection['Username'],
                                       in_connection['Password'],
                                       in_connection['Tableau Site'])
        self.tableau_server.auth.sign_in(tableau_auth)
        local_logger.debug(
            self.locale.gettext(
                'Connection to the Tableau Server has been established successfully!'
            ))
        timer.stop()

    def disconnect_from_tableau_server(self, local_logger, timer):
        timer.start()
        self.tableau_server.auth.sign_out()
        local_logger.debug(
            self.locale.gettext(
                'Connection to the Tableau Server has been terminated!'))
        timer.stop()

    @staticmethod
    def get_project_relevancy(relevant_projects_to_filter, filtering_type,
                              current_project):
        relevant = 0
        if filtering_type == 'JustOnesMentioned':
            if current_project.name.replace(
                    chr(8211), chr(45)) in relevant_projects_to_filter:
                relevant = 1
        elif filtering_type == 'OnesMentionedMarked':
            relevant = 2
        elif filtering_type == 'All':
            relevant = 99
        return relevant

    def is_publishing_possible(self, local_logger, relevant_project_name,
                               relevant_project_ids):
        publish_possible = False
        int_found_projects = len(relevant_project_ids)
        if int_found_projects == 0:
            local_logger.error(
                self.locale.gettext(
                    'No project with provided name "{project_name}" has been found'
                ).replace('{project_name}', relevant_project_name))
            self.no_publishing_feedback()
        elif int_found_projects > 1:
            local_logger.error(
                f'There are {str(int_found_projects)} projects with provided name "'
                + relevant_project_name +
                ' but a unique identifier is expected')
            self.no_publishing_feedback()
        else:
            publish_possible = True
            local_logger.info(
                self.locale.gettext(
                    'A single project identifier was found "{project_guid}", '
                    + 'so I will proceed with publishing provided file there').
                replace('{project_guid}', relevant_project_ids[0]))
            local_logger.info(
                self.locale.gettext('Stay tuned for the confirmation'))
        return publish_possible

    def load_tableau_project_ids(self, local_logger, timer,
                                 in_projects_to_filter, in_filter_type):
        timer.start()
        project_items, pagination_item = self.tableau_server.projects.get(
            req_options=self.req_opts)
        local_logger.info(
            self.locale.gettext(
                'Reading list of all projects available has been completed'))
        local_logger.info(
            self.locale.gettext(
                'A number of {projects_counted} projects have been identified'
            ).replace('{projects_counted}', str(len(project_items))))
        timer.stop()
        timer.start()
        dictionary_project_ids = []
        project_counter = 0
        for project_current in project_items:
            relevant = self.get_project_relevancy(in_projects_to_filter,
                                                  in_filter_type,
                                                  project_current)
            if relevant >= 1:
                dictionary_project_ids.append(project_counter)
                dictionary_project_ids[project_counter] = project_current.id
                project_counter = project_counter + 1
        local_logger.info(
            self.locale.gettext(
                'Retaining the projects according to filtering type provided ({filter_type}) '
                + 'has been completed').replace('{filter_type}',
                                                in_filter_type))
        local_logger.info(
            self.locale.gettext(
                'A number of {projects_counted} projects have been identified'
            ).replace('{projects_counted}', str(len(dictionary_project_ids))))
        timer.stop()
        return dictionary_project_ids

    def no_publishing_feedback(self, local_logger):
        local_logger.debug(
            self.locale.gettext('No publishing action will take place!'))
        local_logger.debug(
            self.locale.gettext(
                'Check your input parameter values for accuracy and try again!'
            ))

    def publish_data_source_to_tableau_server(self, local_logger, timer,
                                              publish_details):
        timer.start()
        local_logger.info(self.locale.gettext('About to start publishing'))
        data_source_name = Path(publish_details['Tableau Extract File'])\
            .name.replace('.hyper', '') + " Extract"
        project_data_source = tsc.DatasourceItem(publish_details['Project ID'],
                                                 data_source_name)
        self.tableau_server.datasources.publish(
            project_data_source, publish_details['Tableau Extract File'],
            publish_details['Publishing Mode'])
        local_logger.info(
            self.locale.gettext('Publishing completed successfully!'))
        timer.stop()
Ejemplo n.º 11
0
def main():
    parser = argparse.ArgumentParser(description='Filter on groups')
    parser.add_argument('--server', '-s', required=True, help='server address')
    parser.add_argument('--username',
                        '-u',
                        required=True,
                        help='username to sign into server')
    parser.add_argument('--logging-level',
                        '-l',
                        choices=['debug', 'info', 'error'],
                        default='error',
                        help='desired logging level (set to error by default)')
    parser.add_argument('-p', default=None)
    args = parser.parse_args()

    if args.p is None:
        password = getpass.getpass("Password: "******"SALES NORTHWEST"
        create_example_group(group_name, server)

        group_name = 'SALES ROMANIA'
        # Try to create a group named "SALES ROMANIA"
        create_example_group(group_name, server)

        # URL Encode the name of the group that we want to filter on
        # i.e. turn spaces into plus signs
        filter_group_name = 'SALES+ROMANIA'
        options = TSC.RequestOptions()
        options.filter.add(
            TSC.Filter(TSC.RequestOptions.Field.Name,
                       TSC.RequestOptions.Operator.Equals, filter_group_name))

        filtered_groups, _ = server.groups.get(req_options=options)
        # Result can either be a matching group or an empty list
        if filtered_groups:
            group_name = filtered_groups.pop().name
            print(group_name)
        else:
            error = "No project named '{}' found".format(filter_group_name)
            print(error)

        options = TSC.RequestOptions()
        options.filter.add(
            TSC.Filter(TSC.RequestOptions.Field.Name,
                       TSC.RequestOptions.Operator.In,
                       ['SALES+NORTHWEST', 'SALES+ROMANIA', 'this_group']))

        options.sort.add(
            TSC.Sort(TSC.RequestOptions.Field.Name,
                     TSC.RequestOptions.Direction.Desc))

        matching_groups, pagination_item = server.groups.get(
            req_options=options)
        print('Filtered groups are:')
        for group in matching_groups:
            print(group.name)
def main():

    parser = argparse.ArgumentParser(
        description=
        "Demonstrate pagination on the list of workbooks on the 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",
        "-n",
        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:
    # No additional options, yet. If you add some, please add them here

    args = parser.parse_args()

    # 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):
        you = server.users.get_by_id(server.user_id)
        print(you.name, you.id)
        # 1. Pager: Pager takes a server Endpoint as its first parameter, and a RequestOptions
        # object as the second parameter. The Endpoint defines which type of objects it returns, and
        # RequestOptions defines any restrictions on the objects: filter by name, sort, or select a page
        print("Your server contains the following workbooks:\n")
        count = 0
        # Using a small number here so that you can see it work. Default is 100 and mostly doesn't need to change
        page_options = TSC.RequestOptions(1, 5)
        print("Fetching workbooks in pages of 5")
        for wb in TSC.Pager(server.workbooks, page_options):
            print(wb.name)
            count = count + 1
        print("Total: {}\n".format(count))

        count = 0
        page_options = TSC.RequestOptions(2, 3)
        print(
            "Paging: start at the second page of workbooks, using pagesize = 3"
        )
        for wb in TSC.Pager(server.workbooks, page_options):
            print(wb.name)
            count = count + 1
        print("Truncated Total: {}\n".format(count))

        print("Your id: ", you.name, you.id, "\n")
        count = 0
        filtered_page_options = TSC.RequestOptions(1, 3)
        filter_owner = TSC.Filter("ownerEmail",
                                  TSC.RequestOptions.Operator.Equals,
                                  "*****@*****.**")
        filtered_page_options.filter.add(filter_owner)
        print("Fetching workbooks again, filtering by owner")
        for wb in TSC.Pager(server.workbooks, filtered_page_options):
            print(wb.name, " -- ", wb.owner_id)
            count = count + 1
        print("Filtered Total: {}\n".format(count))

        # 2. QuerySet offers a fluent interface on top of the RequestOptions object
        print("Fetching workbooks again - this time filtered with QuerySet")
        count = 0
        page = 1
        more = True
        while more:
            queryset = server.workbooks.filter(
                ownerEmail="*****@*****.**")
            for wb in queryset.paginate(page_number=page, page_size=3):
                print(wb.name, " -- ", wb.owner_id)
                count = count + 1
            more = queryset.total_available > count
            page = page + 1
        print("QuerySet Total: {}".format(count))

        # 3. QuerySet also allows you to iterate over all objects without explicitly paging.
        print("Fetching again - this time without manually paging")
        for i, wb in enumerate(
                server.workbooks.filter(owner_email="*****@*****.**"),
                start=1):
            print(wb.name, "--", wb.owner_id)

        print(f"QuerySet Total, implicit paging: {i}")
Ejemplo n.º 13
0
def main():

    parser = argparse.ArgumentParser(
        description='Download pdf file of snapshot(s) of a tableau dashboard.')
    parser.add_argument('--server', '-s', required=True, help='server address')
    parser.add_argument('--token-name',
                        '-tn',
                        required=True,
                        help='user token name')
    parser.add_argument('--token-secret',
                        '-ts',
                        required=True,
                        help='user token secret')
    parser.add_argument('--view-name',
                        '-v',
                        required=True,
                        help='name of dashboard view')
    parser.add_argument('--csv',
                        '-csv',
                        required=False,
                        help='csv dataframe of filters/parameters')
    parser.add_argument('--filepath',
                        '-f',
                        required=True,
                        help='filepath to save the pdf file returned')

    args = parser.parse_args()

    #signs user into server using token access
    tableau_auth = TSC.PersonalAccessTokenAuth(args.token_name,
                                               args.token_secret, '')
    server = TSC.Server(args.server, use_server_version=True)
    server.auth.sign_in(tableau_auth)

    #query for the view that we want an image of
    with server.auth.sign_in(tableau_auth):
        req_option = TSC.RequestOptions()
        req_option.filter.add(
            TSC.Filter(TSC.RequestOptions.Field.Name,
                       TSC.RequestOptions.Operator.Equals, args.view_name))
        all_views, pagination_item = server.views.get(req_option)

        if not all_views:
            raise LookupError("View with the specified name was not found.")

        view_item = all_views[0]

        #adds filter/parameters to the view if .csv included in argument
        if args.csv is not None:
            filters = pd.read_csv(args.csv)
            path_names = [0] * filters.shape[0]
            for i, j in filters.iterrows():
                image_req_option = TSC.ImageRequestOptions(
                    imageresolution=TSC.ImageRequestOptions.Resolution.High)
                for col in filters.columns:
                    image_req_option.vf(col, str(j[col]).replace(', ', ','))

                server.views.populate_image(view_item, image_req_option)

                #temporarily saves each view as separate .png files
                with open('py_img_%i.png' % i, "wb") as image_file:
                    image_file.write(view_item.image)
                    path_names[i] = ('py_img_%i.png' % i)

        #takes a snapshot of the default view, when .csv not included
        else:
            image_req_option = TSC.ImageRequestOptions(
                imageresolution=TSC.ImageRequestOptions.Resolution.High)
            server.views.populate_image(view_item, image_req_option)

            #temporarily saves view as .png
            with open('py_img_0.png', "wb") as image_file:
                image_file.write(view_item.image)
                path_names = ['py_img_0.png']

        #converts mode to remove alpha channel to allow .pdf conversion
        for path in path_names:
            img = Image.open(path)
            if img.mode == 'RGBA':
                img.convert('RGB').save(path)

        #save images as single .pdf
        with open(args.filepath, "wb") as f:
            f.write(img2pdf.convert(path_names))

        #removes temporary .png file(s) from folder
        for path in path_names:
            os.remove(path)
def make_filter(**kwargs):
    options = TSC.RequestOptions()
    for item, value in kwargs.items():
        name = getattr(TSC.RequestOptions.Field, item)
        options.filter.add(TSC.Filter(name, TSC.RequestOptions.Operator.Equals, value))
    return options
Ejemplo n.º 15
0
import tableauserverclient as TSC
from config import password, username
import pandas as pd
from db_connection import importer, run_query_non_results, query_text

#sign in to tableau sever
tableau_auth = TSC.TableauAuth(username, password, site_id='PeopleAnalytics')
request_options = TSC.RequestOptions(pagesize=1000)  #Set page size options
server = TSC.Server('https://tableau.we.co/')
with server.auth.sign_in(tableau_auth):

    #creating table of usernames and workbook permission

    #creates a list of all workbook on the server
    list_workbooks = []

    #creates a list of all users on server
    list_users = []

    #getting all users
    all_users, pagination_item = server.users.get()
    x = 0
    #iterating through users and populating workbooks for each user
    for x in range(len(all_users)):
        page_n = server.users.populate_workbooks(all_users[x])
        for workbook in all_users[x].workbooks:
            list_users.append(all_users[x].name)
            list_workbooks.append(workbook.name)
            x + 1
    #creating a dataframe for all users and workbooks
    data1 = pd.DataFrame({
Ejemplo n.º 16
0
def getViews(servername):
    # return a list of views found on a given server, site, project, and with a particular name
    views = []
    return_list = []
    sites = getSites(servername)

    for site in sites:
        if args.si:
            # if filtered to a site, skip all but the one we want
            if site.name != args.si:
                continue

        tableau_auth = TSC.TableauAuth(args.u,
                                       password,
                                       site_id=site.content_url)
        server = TSC.Server(servername)
        server.add_http_options({'verify': False})
        server.version = APIVERSION

        with server.auth.sign_in(tableau_auth):
            log.logger.info(
                f"signed in to {servername}, {site.name}, {site.content_url}, {site.state}"
            )
            req_option = TSC.RequestOptions()

            # get the server information
            server_info = server.server_info.get()

            # if workbook name passed, filter on it
            if args.wi:
                req_option.filter.add(
                    TSC.Filter(TSC.RequestOptions.Field.Name,
                               TSC.RequestOptions.Operator.Equals, args.wi))

            # if filtering by project, add that criteria
            if args.pi:
                req_option.filter.add(
                    TSC.Filter(TSC.RequestOptions.Field.ProjectName,
                               TSC.RequestOptions.Operator.Equals, args.pi))

            if args.wi or args.pi:
                # get the filtered workbooks, then derive the views from them
                filtered_workbooks = list(
                    TSC.Pager(server.workbooks, req_option))
                filtered_views = []
                for workbook in filtered_workbooks:
                    server.workbooks.populate_views(workbook)
                    filtered_views.extend(workbook.views)
                    log.logger.debug(f'Found {len(filtered_views)} views')
            else:
                # no filtering, so just grab all the views on the site
                filtered_views = list(TSC.Pager(server.views))

            # if filtering by file, remove any non-matches
            if args.vi:
                log.logger.debug(
                    f'filtering views to those provided in {args.vi}')
                view_list = []
                with open(args.vi, newline='') as view_list_file:
                    view_list_reader = csv.reader(view_list_file)
                    log.logger.debug('iterating over the views found')
                    for line in view_list_reader:
                        view_list.append(line[0])

                file_filtered_views = []
                for view in filtered_views:
                    for luid in view_list:
                        if view.id == luid:
                            file_filtered_views.append(view)
                log.logger.debug(
                    f'will run over {len(file_filtered_views)} views')
                time.sleep(5)
                filtered_views = file_filtered_views

        log.logger.debug(f'Final count is {len(filtered_views)} views')

        # now package up the return list views with their contextual information
        for view in filtered_views:
            return_list.append(SiteView(view, site, server, server_info))
        # views.append({"site_content_url": site.content_url, "views": filtered_views})

    return return_list
Ejemplo n.º 17
0
def CSV_ImageRequest(server, tableau_auth, csv_filename, end_file_directory,
                     WorkbookName, DashboardName, UserEmail):

    with server.auth.sign_in(tableau_auth):

        folderExplore.TableauFolderViews(server)

        req_option1 = TSC.RequestOptions()
        req_option1.filter.add(
            TSC.Filter(TSC.RequestOptions.Field.Name,
                       TSC.RequestOptions.Operator.Equals, DashboardName))

        req_option2 = TSC.RequestOptions()
        req_option2.filter.add(
            TSC.Filter(TSC.RequestOptions.Field.Name,
                       TSC.RequestOptions.Operator.Equals, WorkbookName))

        all_views_filtered, views_items1 = server.views.get(req_option1)
        all_workbooks_filtered, workbooks_items1 = server.workbooks.get(
            req_option2)

        view_i, workbook_i = folderExplore.checkMatch(all_views_filtered,
                                                      views_items1,
                                                      all_workbooks_filtered,
                                                      workbooks_items1)

        with open(csv_filename) as csv_file:
            csv_reader = csv.reader(csv_file, delimiter=',')
            line_count = 0

            for row in csv_reader:
                if line_count == 0:
                    num_col = len(row)
                    column_header = row
                    print("\n {}".format(column_header))
                    line_count += 1
                else:
                    if (row[1] == "PNG" or row[1] == "JPG"):

                        # view item is the dashboard view.
                        view_item = all_views_filtered[view_i]

                        image_req_option = TSC.ImageRequestOptions(
                            imageresolution=TSC.ImageRequestOptions.Resolution.
                            High)

                        # Assumes col 0,1,2 are imageName, FileType, and Email respectively

                        for iter_ in range(3, num_col):
                            # column_header[iter_] takes the nth item across in column header,
                            # row header [iter_] takes the same nth item acrpss in the row
                            # pases it to like this:
                            # image_req_option.vf( Color By , 2)
                            # image_req_option.vf( Bubble Color, 1)
                            # image_req_option.vf( Sales Channel, Channel1)
                            if (row[iter_] == "All"):
                                image_req_option.view_filters.clear()
                                break
                            else:
                                image_req_option.vf(column_header[iter_],
                                                    row[iter_])

                        server.views.populate_image(view_item,
                                                    image_req_option)
                        image_filepath = view_item.name

                        with open(
                                end_file_directory + "/" + image_filepath +
                                row[0] + "." + row[1], "wb") as image_file:
                            image_file.write(view_item.image)

                    elif (row[1] == "PDF"):

                        view_item = all_views_filtered[view_i]

                        pdf_req_option = TSC.PDFRequestOptions(
                            page_type=TSC.PDFRequestOptions.PageType.A4,
                            orientation=TSC.PDFRequestOptions.Orientation.
                            Portrait)

                        # Assumes col 0,1,2 are imageName, FileType, and Email respectively
                        for iter_ in range(3, num_col):
                            if (row[iter_] == "All"):
                                pdf_req_option.view_filters.clear()
                                break
                            else:
                                pdf_req_option.vf(column_header[iter_],
                                                  row[iter_])

                        server.views.populate_pdf(view_item, pdf_req_option)
                        pdf_name = view_item.name

                        with open(
                                end_file_directory + "/" + pdf_name + row[0] +
                                "." + row[1], "wb") as pdf_file:
                            pdf_file.write(view_item.pdf)

                            # full_path = end_file_directory + "/" + pdf_name + row[0] + "." + row[1]
                            # emailScript.email_singlePDF(row[2], full_path, row[0], UserEmail)

                    print(row)
                    line_count += 1

            print(f'Processed {line_count} lines.')

    server.auth.sign_out()
Ejemplo n.º 18
0
def handler(event, context):
    logger.info(event)
    session = boto3.Session(region_name='us-east-1')
    ssm = session.client('ssm')
    user = ssm.get_parameter(Name='/tableau/user',
                             WithDecryption=True)['Parameter']['Value']
    password = ssm.get_parameter(Name='/tableau/password',
                                 WithDecryption=True)['Parameter']['Value']

    body = json.loads(event['body'])
    extract_responses = []
    for item in body['payload']:
        server_name = item['server']
        host = ssm.get_parameter(
            Name=f"/tableau/{server_name}/host")['Parameter']['Value']

        logger.info(f"Connecting to {server_name} server")
        server = TSC.Server(host, use_server_version=True)
        auth = TSC.TableauAuth(user, password)

        with server.auth.sign_in(auth):
            for extract in item['extracts']:
                extract_name = extract

                ro = TSC.RequestOptions()
                filter = TSC.Filter(TSC.RequestOptions.Field.Name,
                                    TSC.RequestOptions.Operator.Equals,
                                    extract_name)
                ro.filter.add(filter)

                resource, pagination = server.datasources.get(ro)
                resource = resource[0]
                logger.info(f'Refreshing datasource - {resource.name}')
                tableau_response = server.datasources.refresh(resource)
                extract_response = {
                    'server': server_name,
                    'name': resource.name,
                    'queued_at': None,
                    'errors': []
                }
                try:
                    created_at = tableau_response.created_at
                    message = f'{resource.name} extract queued at {created_at}'
                    logger.info(message)
                    extract_response['queued_at'] = str(created_at)
                except AttributeError:
                    message = f'There was an error starting {resource.name}'
                    logger.info(message)
                    logger.error(tableau_response)
                    extract_response['errors'].append(message)
                extract_responses.append(extract_response)

    return {
        'headers': {
            'content-type': 'application/json'
        },
        'statusCode': 200,
        'body': json.dumps({
            'message': 'Success',
            'extracts': extract_responses
        })
    }
Ejemplo n.º 19
0
def main():
    parser = argparse.ArgumentParser(
        description='List project details available on a server')
    parser.add_argument('--server', '-s', required=True, help='server address')
    parser.add_argument('--username',
                        '-u',
                        required=True,
                        help='username to sign into server')
    parser.add_argument('--site', '-S', default=None)
    parser.add_argument('-p', default=None)

    parser.add_argument('--logging-level',
                        '-l',
                        choices=['debug', 'info', 'error'],
                        default='error',
                        help='desired logging level (set to error by default)')

    parser.add_argument('project',
                        help='one or more projects to list',
                        nargs='+')

    args = parser.parse_args()

    if args.p is None:
        password = getpass.getpass("password: "******"no project named '{}' found".format(
                    filter_project_name)
                print(error)

            server.projects.populate_permissions(project)
            print("{0}: {1}".format(project.name, project.content_permissions))
            print("==================================================")

            userOptions = TSC.UserRequestOptions(
                details=TSC.UserRequestOptions.Details.All)
            users_site, _ = server.users.get(userOptions)
            users = dict([(u.id, u) for u in users_site])

            groups, _ = server.groups.get()
            for g in groups:
                print("group: {0}".format(g.name))
                server.groups.populate_users(g)
                for user in g.users:
                    print("{0} ({1}): {2}, {3}".format(
                        users[user.id].name, users[user.id].site_role,
                        users[user.id].fullname, users[user.id].email))
                print("--------------------------------------------------")
            print("==================================================")

            for c in project.permissions.grantee_capabilities:
                #print("{0}: {1}, {2}".format(c.grantee_id, c.grantee_type, c.capabilities))
                if c.grantee_type == 'group':
                    group = [g for g in groups if g.id == c.grantee_id].pop()
                    print("{0}: {1}".format(group.name, c.capabilities))
                if c.grantee_type == 'user':
                    print("{0}: {1}".format(users[c.grantee_id].name,
                                            c.capabilities))
            print("==================================================")
Ejemplo n.º 20
0
def main():
    '''主函数
    '''
    # 连接tableau server
    request_options = TSC.RequestOptions(pagesize=200)

    tableau_auth = TSC.TableauAuth('20040201', 'GT2020!qaz', site_id='')
    # tableau_auth = TSC.TableauAuth('GT_Account', 'GT2020123456', site_id='')
    # server = TSC.Server('https://fas-gt.com:8000', use_server_version=True)
    server = TSC.Server('https://tab.sucgm.com:10000', use_server_version=True)

    nowTime = datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S')  # 现在
    content = fwapi()
    infos = content['data']
    # print("输出本次全部数据:",infos)
    connect = sqlcon()
    workgroup = []
    cursor = connect.cursor()  # 创建一个游标对象,python里的sql语句都要通过cursor来执行

    # 1. 创建文件对象
    f = open('user&pwd-' + nowTime + '.csv',
             'w',
             encoding='utf-8',
             newline=''
             "")
    # 2. 基于文件对象构建 csv写入对象
    csv_writer = csv.writer(f)

    # 3. 构建列表头
    csv_writer.writerow(["Workcode", "Password"])
    tbgroup = tabgroup(server, tableau_auth, request_options)
    tbuser = tabuser(server, tableau_auth, request_options)

    # 本次新加入用户计数器
    addCount = 0
    addRecord = []
    # 本次离职人数计数器
    quitCount = 0

    # 系统账户(不可删除)
    SystemUser = ['SHCJTS_Admin', '20040201', 'RPA_Account']

    for info in infos:
        # 遍历获取员工信息号和群组名称
        workcode = info['workcode']
        # workcode = 'A0716'
        groupidnew = info['rolesmark']
        status = info['status']
        if status == '1':
            groupidnew = groupidnew[:-5]  # 将群组名称后的 -致同群组 字段删除
            workgroup.append([workcode, groupidnew])
            print(workcode)
            # 查询FW_Users库内对应workcoode 人员状态信息
            sql = "select * from OFW_USER_TAB_ALLOWED where IsDelete = 0 and MemberCode = %s"
            # sql = "select * from OFW_USER_TAB_ALLOWED where  MemberCode = %s"
            # sql = "select * from OFW_USER_TAB_ALLOWED_TEST where IsDelete = 0 and MemberCode = %s"
            cursor.execute(sql, workcode)  # 执行sql语句
            row = cursor.fetchall()  # 读取查询结果,
            rowCount = len(row)
            print(row)
            # for n in row:
            #     print(n[1])
            print(workcode, "该员工当前在Tableau Server对应群组记录数", rowCount)
            # time.sleep(5)

            # 查询用户是否已存在 若不存在 创建新用户并加入相应群组
            if rowCount == 0:
                # 查询该用户是否之前曾有过群组的记录
                sql = "select * from OFW_USER_TAB_ALLOWED where IsDelete = 1 and MemberCode = %s and GroupID= %s"
                # sql = "select * from OFW_USER_TAB_ALLOWED_TEST where IsDelete = 0 and MemberCode = %s and GroupID= %s"
                value = (workcode, groupidnew)
                cursor.execute(sql, value)  # 执行sql语句
                row = cursor.fetchall()  # 读取查询结果,
                rowCount = len(row)
                if rowCount != 0:
                    sql = "UPDATE OFW_USER_TAB_ALLOWED SET IsDelete =0 WHERE MemberCode = %s and GroupID= %s"
                    # sql = "UPDATE OFW_USER_TAB_ALLOWED_TEST SET IsDelete =0 WHERE MemberCode = %s and GroupID= %s"
                    cursor.execute(sql, value)
                    connect.commit()
                    addCount = addCount + 1
                    with server.auth.sign_in(tableau_auth):
                        # 将用户加入群组
                        # index = getTwoDimensionListIndex(tbgroup, groupidnew)
                        user = getTwoDimensionListIndex(tbuser, workcode)
                        # print(user)
                        all_groups, pagination_item = server.groups.get(
                            request_options)
                        for group in all_groups:
                            if group.name == groupidnew:
                                server.groups.add_user(group, tbuser[user][0])
                                break
                else:
                    with server.auth.sign_in(tableau_auth):
                        # 先查询用户是否存在

                        # 将新用户添加至user表
                        newU = TSC.UserItem(workcode, 'Viewer')
                        # add the new user to the site
                        newU = server.users.add(newU)
                        # 将用户的id,name加入tbuser
                        tbuser.append([newU.id, newU.name])
                        # 更新详细信息
                        newU.fullname = workcode
                        # index = getTwoDimensionListIndex(tbgroup, groupidnew)

                        # 加入群组
                        # if index !="不存在该值":
                        all_groups, pagination_item = server.groups.get(
                            request_options)
                        for group in all_groups:
                            if group.name == groupidnew:
                                server.groups.add_user(group, newU.id)
                                break
                        # else:
                        #     print(index)
                        pwd = pwdcreate()
                        csv_writer.writerow([workcode, pwd])
                        user1 = server.users.update(newU, password=pwd)
                    sql2 = "insert into OFW_USER_TAB_ALLOWED (MemberCode,GroupID) VALUES (%s,%s)"
                    # sql2 = "insert into OFW_USER_TAB_ALLOWED_TEST (MemberCode,GroupID) VALUES (%s,%s)"
                    value = (workcode, groupidnew)
                    cursor.execute(sql2, value)
                    connect.commit()
                    print('完成账号 ' + workcode + ' 在群组 ' + groupidnew + ' 的添加')
                    addCount = addCount + 1
                    addRecord.append([workcode, groupidnew])

            # 用户已存在的情况
            else:
                # 查询该用户是否之前曾有过群组的记录
                sql = "select * from OFW_USER_TAB_ALLOWED where IsDelete = 1 and MemberCode = %s and GroupID= %s"
                # sql = "select * from OFW_USER_TAB_ALLOWED_TEST where IsDelete = 1 and MemberCode = %s and GroupID= %s"
                value = (workcode, groupidnew)
                cursor.execute(sql, value)  # 执行sql语句
                rowold = cursor.fetchall()  # 读取查询结果,
                rowCount = len(rowold)
                # 无群组记录
                if rowCount != 0:  # rowCount不为0 说明该用户在该群组之前有记录被删除,将isdel置0#
                    sql = "UPDATE OFW_USER_TAB_ALLOWED SET IsDelete =0 WHERE MemberCode = %s and GroupID= %s"
                    # sql = "UPDATE OFW_USER_TAB_ALLOWED_TEST SET IsDelete =0 WHERE MemberCode = %s and GroupID= %s"
                    cursor.execute(sql, value)
                    connect.commit()
                    with server.auth.sign_in(tableau_auth):
                        # 将用户加入群组
                        # index = getTwoDimensionListIndex(tbgroup, groupidnew)
                        user = getTwoDimensionListIndex(tbuser, workcode)
                        # print(user)
                        all_groups, pagination_item = server.groups.get(
                            request_options)
                        for group in all_groups:
                            if group.name == groupidnew:
                                server.groups.add_user(group, tbuser[user][0])
                                print('完成账号 ' + workcode + ' 在群组 ' +
                                      groupidnew + ' 的添加')
                                addCount = addCount + 1
                                addRecord.append([workcode, groupidnew])
                                break
                else:
                    oldgroup = []
                    # 该员工原有的群组
                    for n in row:
                        oldgroup.append(n[1])
                        # api传递的数据是一一对应的情况
                    print(workcode, "该员工对应原有群组", oldgroup)
                    if groupidnew not in oldgroup:
                        with server.auth.sign_in(tableau_auth):
                            # 将用户加入群组
                            # index = getTwoDimensionListIndex(tbgroup, groupidnew)
                            user = getTwoDimensionListIndex(tbuser, workcode)
                            print(user)
                            all_groups, pagination_item = server.groups.get(
                                request_options)
                            for group in all_groups:
                                if group.name == groupidnew:
                                    server.groups.add_user(
                                        group, tbuser[user][0])
                                    break

                            # 更新详细信息
                            # newU.name = 'test'
                            # newU.fullname = workcode
                            sql2 = "insert into OFW_USER_TAB_ALLOWED (MemberCode,GroupID) VALUES (%s,%s)"
                            # sql2 = "insert into OFW_USER_TAB_ALLOWED_TEST (MemberCode,GroupID) VALUES (%s,%s)"
                            value = (workcode, groupidnew)
                            cursor.execute(sql2, value)
                            connect.commit()
                            print('完成账号 ' + workcode + ' 在群组 ' + groupidnew +
                                  ' 的添加')
                            addCount = addCount + 1
                            addRecord.append([workcode, groupidnew])
    f.close()
    cursor = connect.cursor()  # 创建一个游标对象,python里的sql语句都要通过cursor来执行
    # 查询群组表内的群组信息
    sql = "select GroupName from OFW_GROUP_TAB_ALLOWED"
    # sql = "select GroupName from OFW_GROUP_TAB_ALLOWED_TEST"
    cursor.execute(sql)  # 执行sql语句
    rowgroup = cursor.fetchall()  # 读取查询结果,
    # rowCount = len(row)
    for groupid in rowgroup:
        # print(groupid)
        groupid = groupid[0]
        # 查询表内对应该群组的workcode
        sqls = "select MemberCode from OFW_USER_TAB_ALLOWED where GroupID= %s and IsDelete =0"
        # sqls = "select MemberCode from OFW_USER_TAB_ALLOWED_TEST where GroupID= %s"
        cursor.execute(sqls, groupid)  # 执行sql语句
        rowidingroups = cursor.fetchall()  # 读取查询结果,
        # print(rowidingroups)
        for rowidingroup in rowidingroups:
            rawdata = rowidingroup[0]
            # 此处注意判断是否有另外开的账号 需要加在指定群组中 但不在泛微数据中
            if [rawdata, groupid] not in workgroup:
                # 通过tsc 获取id 在group中删除
                # indexgroup=getTwoDimensionListIndex(tbgroup,groupid)
                indexuser = getTwoDimensionListIndex(tbuser, rawdata)
                with server.auth.sign_in(tableau_auth):
                    # mygroup = tbgroup[indexgroup][0]
                    userdel = tbuser[indexuser][0]
                    all_groups, pagination_item = server.groups.get(
                        request_options)
                    for group in all_groups:
                        if group.name == groupid:
                            server.groups.remove_user(group, userdel)
                            # 若该群组不存在 进行逻辑删除
                            sql = "UPDATE OFW_USER_TAB_ALLOWED SET IsDelete =1 WHERE MemberCode = %s and GroupID= %s"
                            # sql = "UPDATE OFW_USER_TAB_ALLOWED_TEST SET IsDelete =1 WHERE MemberCode = %s and GroupID= %s"
                            value = (rawdata, groupid)
                            cursor.execute(sql, value)
                            # 提交到数据库执行
                            connect.commit()
                            break
                    print('完成对 ' + rawdata + " 在群组 " + groupid + " 的删除操作")

    for userid in tbuser:
        # 判断是否为非城建用户
        if userid[1] not in SystemUser:
            sql = "select * from DW_HR_MEMBER where MemberMsgCode = %s AND snapdate = CONVERT(DATE,GETDATE(),110)"
            cursor.execute(sql, userid[1])  # 执行sql语句
            row = cursor.fetchall()  # 读取查询结果,
            rowCount = len(row)
            # 为0代表用户已离职 从tableau server端删除 计数器+1
            if rowCount == 0:
                with server.auth.sign_in(tableau_auth):
                    server.users.remove(userid[0])
                    print('员工' + userid[1] + '已离职,从Tableau Server端删除成功')
                    quitCount = quitCount + 1

    print('本次共删除用户' + str(quitCount) + '人')

    # 统计各群组新增用户
    if addRecord:
        for record in addRecord:
            print('本次已完成对用户 ' + record[0] + ' 在群组 ' + record[1] + '中的添加')

    print('本次完成群组新增' + str(addCount) + '人')
Ejemplo n.º 21
0
def main():
    logger.debug('Loading config...')
    config = configparser.ConfigParser()
    config_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'tableausync.conf')
    config.read_file(open(config_path))

    config_sections = config.sections()

    do_something = config.get('Common', 'do_something')
    if do_something in ['True']:
        do_something = True
        logger.info('This is the real deal, updating data in the system')
    else:
        do_something = False
        logger.info('It is TEST RUN')

    ad_server = config.get('AD', 'server')
    ad_user = config.get('AD', 'user')
    ad_password = config.get('AD', 'password')
    tableau_root_ou = config.get('AD', 'tableau_root_ou')
    users_root_ou = config.get('AD', 'users_root_ou')
    tableau_server = config.get('Tableau', 'server')
    tableau_admin = config.get('Tableau', 'username')
    tableau_password = config.get('Tableau', 'password')

    ad = AD(ad_server, ad_user, ad_password, tableau_root_ou, users_root_ou)
    
    tableau_auth = TSC.TableauAuth(tableau_admin, tableau_password)
    tableau_server = TSC.Server(tableau_server)

    with tableau_server.auth.sign_in(tableau_auth):
        opts = TSC.RequestOptions(pagesize=1000)
        tableau_all_site_users = [user for user in TSC.Pager(tableau_server.users) if user.site_role != 'Unlicensed']
        tableau_unlicensed_users = [user for user in TSC.Pager(tableau_server.users) if user.site_role == 'Unlicensed']
            
        for group in TSC.Pager(tableau_server.groups):
            # get ad_members_set for this group
            if(not group.name == 'All Users'):
                logger.info("Getting AD Group Members for: {}".format(group.name))
                ad_members = ad.get_members_by_groupname(group.name)
                ad_members_set = set([user.sAMAccountName.value for user in ad_members])
                logger.info("AD Members #: {}".format(len(ad_members_set)))

                # get tab_members_set for this group
                logger.info("Getting Tableau Group Members for: {}".format(group.name))
                tableau_server.groups.populate_users(group, opts)
                tableau_members_set = set([user.name for user in group.users])
                logger.info("Tableau Members #: {}".format(len(tableau_members_set)))

                add_members = ad_members_set - tableau_members_set
                remove_members = tableau_members_set - ad_members_set

                logger.info("Group {} - Adding Users: {}".format(group.name, add_members))
                logger.info("Group {} - Removing Users: {}".format(group.name, remove_members))


                if do_something:
                    for new_member in add_members:
                        logger.debug("Adding user:{0}".format(new_member))
                        user_id = [user.id for user in tableau_all_site_users if user.name == new_member].pop()
                        tableau_server.groups.add_user(user_id=user_id, group_item=group)

                if do_something:
                    for old_member in remove_members:
                        logger.debug("Removing user:{0}".format(old_member))
                        user_id = [user.id for user in tableau_all_site_users if user.name == old_member][0]
                        tableau_server.groups.remove_user(user_id=user_id, group_item=group)
Ejemplo n.º 22
0
def setPagination():
    return TSC.RequestOptions(pagesize=1000)
Ejemplo n.º 23
0
def main():
    parser = argparse.ArgumentParser(description='Filter and sort projects.')
    parser.add_argument('--server', '-s', required=True, help='server address')
    parser.add_argument('--username', '-u', required=True, help='username to sign into server')
    parser.add_argument('--site', '-S', default=None)
    parser.add_argument('-p', default=None)

    parser.add_argument('--logging-level', '-l', choices=['debug', 'info', 'error'], default='error',
                        help='desired logging level (set to error by default)')

    args = parser.parse_args()

    if args.p is None:
        password = getpass.getpass("Password: "******"No project named '{}' found".format(filter_project_name)
            print(error)

        create_example_project(name='Example 1', server=server)
        create_example_project(name='Example 2', server=server)
        create_example_project(name='Example 3', server=server)
        create_example_project(name='Proiect ca Exemplu', server=server)

        options = TSC.RequestOptions()

        # don't forget to URL encode the query names
        options.filter.add(TSC.Filter(TSC.RequestOptions.Field.Name,
                                      TSC.RequestOptions.Operator.In,
                                      ['Example+1', 'Example+2', 'Example+3']))

        options.sort.add(TSC.Sort(TSC.RequestOptions.Field.Name,
                                  TSC.RequestOptions.Direction.Desc))

        matching_projects, pagination_item = server.projects.get(req_options=options)
        print('Filtered projects are:')
        for project in matching_projects:
            print(project.name, project.id)
Ejemplo n.º 24
0
def main():

    try:

        tableauPassword, gitPassword, environment, env_site_id = getCreds()

        logger.info('Preparing Backup')

        #setting up tableau login credentials
        tableau_auth = TSC.TableauAuth(cfg['tableauServer']['user'],
                                       tableauPassword,
                                       site_id=env_site_id)
        server = TSC.Server(cfg['tableauServer']['url'],
                            use_server_version=True)

        firstTime = False

        #check if there is git repo, if not clone the repository
        oPath = cfg['git']['projectName']

        #if os.path.isdir(oPath) is False:
        #    Repo.clone_from('http://'+cfg['git']['login']+':'+gitPassword+'@'+cfg['git']['url'].split('://', 1)[1], oPath)
        #    firstTime = True

        if os.path.isdir(oPath) is False:
            git_ssh_identity_file = os.path.expanduser('/home/.ssh/id_rsa')
            git_ssh_cmd = 'ssh -i %s' % git_ssh_identity_file

            with Git().custom_environment(GIT_SSH_COMMAND=git_ssh_cmd):
                Repo.clone_from('git@git_url/repository.git',
                                oPath,
                                branch='develop')
                firstTime = True

        repo = git.Repo(oPath)
        oPath = oPath + "/" + environment

        #logging into tableau server
        server.auth.sign_in(tableau_auth)

        #setting time stamp for one hour previous from when this script is run
        currentTime = datetime.now()
        downloadChangesSince = (datetime.fromtimestamp(
            (currentTime.timestamp() - args.incremental * 3600)).replace(
                microsecond=0)).isoformat() + 'Z'

        if firstTime is True or args.full_load == True:
            downloadChangesSince = '2000-01-01T00:00:00Z'

        req_option = TSC.RequestOptions()
        req_option.filter.add(
            TSC.Filter(TSC.RequestOptions.Field.UpdatedAt,
                       TSC.RequestOptions.Operator.GreaterThanOrEqual,
                       downloadChangesSince))

        remove_punctuation_map = dict(
            (ord(char), None) for char in '\/*?:"<>|')

        #iterating through each site on tableau
        for site in TSC.Pager(server.sites):

            logger.info(
                'Backing up workbooks and datasources under the {} site changed after {}'
                .format(site.name, downloadChangesSince))

            #logging into the specific site
            tableau_auth1 = TSC.TableauAuth(cfg['tableauServer']['user'],
                                            tableauPassword,
                                            site_id=site.content_url)
            server.auth.sign_in(tableau_auth1)

            sPath = os.path.join(oPath,
                                 site.name.translate(remove_punctuation_map))
            if os.path.isdir(sPath) is False:
                os.makedirs(sPath)

            #iterating through each workbook in the specified site to download and extract
            for workbook in TSC.Pager(server.workbooks, req_option):

                workbookName = workbook.project_name.translate(
                    remove_punctuation_map)
                xPath = os.path.join(sPath, workbookName)

                if os.path.isdir(xPath) is False:
                    os.makedirs(xPath)

                file_path = server.workbooks.download(workbook.id,
                                                      filepath=xPath,
                                                      no_extract=True)

                print('----     path    ----------')
                print('----     ' + file_path)
                print('----     ' + site.name)
                print('----     ' + workbookName)
                print('----     ' + workbook.project_id)
                print('----     ' + workbook.id)
                print('---     /path-----------')

                extractWorkbook(file_path, site.name, workbookName,
                                workbook.project_id, workbook.id,
                                os.path.basename(file_path), xPath)

            #iterating through each datasource in the specified site to downlad and extract
            for datasources in TSC.Pager(server.datasources, req_option):

                datasourcesName = datasources.project_name.translate(
                    remove_punctuation_map)
                dPath = os.path.join(sPath, datasourcesName)

                if os.path.isdir(dPath) is False:
                    os.makedirs(dPath)

                file_path = server.datasources.download(datasources.id,
                                                        filepath=dPath,
                                                        include_extract=False)
                extractDatasource(file_path, site.name, datasourcesName,
                                  datasources.project_id, datasources.id,
                                  os.path.basename(file_path), dPath)

        #pushing changes to git and timestamping when this script was run
        print(repo.git.status())
        if "nothing to commit" not in repo.git.status():
            repo.git.add('.')
            repo.git.commit(m="backup of" + environment + ": " +
                            currentTime.strftime('%Y-%m-%d %H-%M-%S'))
            repo.git.push('origin')
            print("backed up to git")

        logger.info('Backup Complete')
        server.auth.sign_out()

    except:
        logging.exception('error')
        pass
def main():

    parser = argparse.ArgumentParser(description="Move one workbook from the"
                                     "default project of the default site to"
                                     "the default project of another site.")
    parser.add_argument('--server', '-s', required=True, help='server address')
    parser.add_argument('--username',
                        '-u',
                        required=True,
                        help='username to sign into server')
    parser.add_argument('--workbook-name',
                        '-w',
                        required=True,
                        help='name of workbook to move')
    parser.add_argument('--destination-site',
                        '-d',
                        required=True,
                        help='name of site to move workbook into')
    parser.add_argument('--logging-level',
                        '-l',
                        choices=['debug', 'info', 'error'],
                        default='error',
                        help='desired logging level (set to error by default)')

    args = parser.parse_args()

    password = getpass.getpass("Password: "******"No site named {} found.".format(
                        args.destination_site)
                    raise LookupError(error)

                tableau_auth.site_id = args.destination_site

                # Signing into another site requires another server object
                # because of the different auth token and site ID.
                with dest_server.auth.sign_in(tableau_auth):

                    # Step 5: Create a new workbook item and publish workbook. Note that
                    # an empty project_id will publish to the 'Default' project.
                    new_workbook = TSC.WorkbookItem(name=args.workbook_name,
                                                    project_id="")
                    new_workbook = dest_server.workbooks.publish(
                        new_workbook,
                        workbook_path,
                        mode=TSC.Server.PublishMode.Overwrite)
                    print("Successfully moved {0} ({1})".format(
                        new_workbook.name, new_workbook.id))

                # Step 6: Delete workbook from source site and delete temp directory
                source_server.workbooks.delete(all_workbooks[0].id)

            finally:
                shutil.rmtree(tmpdir)
def main():

    parser = argparse.ArgumentParser(description="Creates sample schedules for each type of frequency.")
    # 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:
    # This sample has no additional options, yet. If you add some, please add them here

    args = parser.parse_args()

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

    tableau_auth = TSC.PersonalAccessTokenAuth(args.token_name, args.token_value, site_id=args.site)
    server = TSC.Server(args.server, use_server_version=False)
    server.add_http_options({"verify": False})
    server.use_server_version()
    with server.auth.sign_in(tableau_auth):
        # Hourly Schedule
        # This schedule will run every 2 hours between 2:30AM and 11:00PM
        hourly_interval = TSC.HourlyInterval(start_time=time(2, 30), end_time=time(23, 0), interval_value=2)

        hourly_schedule = TSC.ScheduleItem(
            "Hourly-Schedule",
            50,
            TSC.ScheduleItem.Type.Extract,
            TSC.ScheduleItem.ExecutionOrder.Parallel,
            hourly_interval,
        )
        try:
            hourly_schedule = server.schedules.create(hourly_schedule)
            print("Hourly schedule created (ID: {}).".format(hourly_schedule.id))
        except Exception as e:
            print(e)

        # Daily Schedule
        # This schedule will run every day at 5AM
        daily_interval = TSC.DailyInterval(start_time=time(5))
        daily_schedule = TSC.ScheduleItem(
            "Daily-Schedule",
            60,
            TSC.ScheduleItem.Type.Subscription,
            TSC.ScheduleItem.ExecutionOrder.Serial,
            daily_interval,
        )
        try:
            daily_schedule = server.schedules.create(daily_schedule)
            print("Daily schedule created (ID: {}).".format(daily_schedule.id))
        except Exception as e:
            print(e)

        # Weekly Schedule
        # This schedule will wun every Monday, Wednesday, and Friday at 7:15PM
        weekly_interval = TSC.WeeklyInterval(
            time(19, 15), TSC.IntervalItem.Day.Monday, TSC.IntervalItem.Day.Wednesday, TSC.IntervalItem.Day.Friday
        )
        weekly_schedule = TSC.ScheduleItem(
            "Weekly-Schedule",
            70,
            TSC.ScheduleItem.Type.Extract,
            TSC.ScheduleItem.ExecutionOrder.Serial,
            weekly_interval,
        )
        try:
            weekly_schedule = server.schedules.create(weekly_schedule)
            print("Weekly schedule created (ID: {}).".format(weekly_schedule.id))
        except Exception as e:
            print(e)
            options = TSC.RequestOptions()
            options.filter.add(
                TSC.Filter(TSC.RequestOptions.Field.Name, TSC.RequestOptions.Operator.Equals, "Weekly Schedule")
            )
            schedules, _ = server.schedules.get(req_options=options)
            weekly_schedule = schedules[0]
            print(weekly_schedule)

        # Monthly Schedule
        # This schedule will run on the 15th of every month at 11:30PM
        monthly_interval = TSC.MonthlyInterval(start_time=time(23, 30), interval_value=15)
        monthly_schedule = TSC.ScheduleItem(
            "Monthly-Schedule",
            80,
            TSC.ScheduleItem.Type.Subscription,
            TSC.ScheduleItem.ExecutionOrder.Parallel,
            monthly_interval,
        )
        try:
            monthly_schedule = server.schedules.create(monthly_schedule)
            print("Monthly schedule created (ID: {}).".format(monthly_schedule.id))
        except Exception as e:
            print(e)

        # Now fetch the weekly schedule by id
        fetched_schedule = server.schedules.get_by_id(weekly_schedule.id)
        fetched_interval = fetched_schedule.interval_item
        print("Fetched back our weekly schedule, it shows interval ", fetched_interval)
Ejemplo n.º 27
0
    print('\nGET THE WORKBOOK BY LUID and its VIEWS >>>')
    workbook = server.workbooks.get_by_id(
        '5fba2c81-76b3-4b29-b24b-0f69eca3703f')
    server.workbooks.populate_views(
        workbook)  #get only the views of that particular workbook
    print('Views of the Workbook uder ID: ', workbook.id, ' (name : ',
          workbook.name, ')', ' are: ', [view.name for view in workbook.views])

    # - 05 - get all usernames and LUIDs
    print('\nGET USERS NAMES AND LUIDs >>>')
    all_users, pagination_item = server.users.get()
    print('All the Users: ', [user.name for user in all_users])
    print('IDs of the Users: ', [user.id for user in all_users])

    # - 06 - get user by name
    print('\nGET USER BY NAME >>>')
    req_option = TSC.RequestOptions()
    req_option.filter.add(
        TSC.Filter(TSC.RequestOptions.Field.Name,
                   TSC.RequestOptions.Operator.Equals, 'User01'))
    matching_user, pagination_item = server.users.get(req_option)
    print('Username is: ', matching_user[0].name, 'and LUID of the user:'******'\nGET WORKBOOKS FOR THE SPECIFIC USER >>>')
    server.users.populate_workbooks(matching_user[0])
    print("The workbooks for", matching_user[0].name, "are :")
    for workbook in matching_user[0].workbooks:
        print(workbook.name)
Ejemplo n.º 28
0
def main():
    parser = argparse.ArgumentParser(description="Filter and sort projects.")
    # 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
    # This sample has no additional options, yet. If you add some, please add them here

    args = parser.parse_args()

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

    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):
        # Use highest Server REST API version available
        server.use_server_version()

        filter_project_name = "default"
        options = TSC.RequestOptions()

        options.filter.add(
            TSC.Filter(TSC.RequestOptions.Field.Name,
                       TSC.RequestOptions.Operator.Equals,
                       filter_project_name))

        filtered_projects, _ = server.projects.get(req_options=options)
        # Result can either be a matching project or an empty list
        if filtered_projects:
            project_name = filtered_projects.pop().name
            print(project_name)
        else:
            error = "No project named '{}' found".format(filter_project_name)
            print(error)

        create_example_project(name="Example 1", server=server)
        create_example_project(name="Example 2", server=server)
        create_example_project(name="Example 3", server=server)
        create_example_project(name="Proiect ca Exemplu", server=server)

        options = TSC.RequestOptions()

        # don't forget to URL encode the query names
        options.filter.add(
            TSC.Filter(TSC.RequestOptions.Field.Name,
                       TSC.RequestOptions.Operator.In,
                       ["Example+1", "Example+2", "Example+3"]))

        options.sort.add(
            TSC.Sort(TSC.RequestOptions.Field.Name,
                     TSC.RequestOptions.Direction.Desc))

        matching_projects, pagination_item = server.projects.get(
            req_options=options)
        print("Filtered projects are:")
        for project in matching_projects:
            print(project.name, project.id)

        # Or, try the django style filtering.
        projects = ["Example 1", "Example 2", "Example 3"]
        projects = [urllib.parse.quote_plus(p) for p in projects]
        for project in server.projects.filter(name__in=projects).sort("-name"):
            print(project.name, project.id)
Ejemplo n.º 29
0
def main():

    parser = argparse.ArgumentParser(
        description='Query View Image From Server')
    parser.add_argument('--server', '-s', required=True, help='server address')
    parser.add_argument('--site-id',
                        '-si',
                        required=False,
                        help='content url for site the view is on')
    parser.add_argument('--username',
                        '-u',
                        required=True,
                        help='username to sign into server')
    parser.add_argument('--view-name',
                        '-v',
                        required=True,
                        help='name of view to download an image of')
    parser.add_argument('--filepath',
                        '-f',
                        required=True,
                        help='filepath to save the image returned')
    parser.add_argument('--logging-level',
                        '-l',
                        choices=['debug', 'info', 'error'],
                        default='error',
                        help='desired logging level (set to error by default)')

    args = parser.parse_args()

    password = getpass.getpass("Password: "******""
    tableau_auth = TSC.TableauAuth(args.username, password, site_id=site_id)
    server = TSC.Server(args.server)
    # The new endpoint was introduced in Version 2.5
    server.version = "2.5"

    with server.auth.sign_in(tableau_auth):
        # Step 2: Query for the view that we want an image of
        req_option = TSC.RequestOptions()
        req_option.filter.add(
            TSC.Filter(TSC.RequestOptions.Field.Name,
                       TSC.RequestOptions.Operator.Equals, args.view_name))
        all_views, pagination_item = server.views.get(req_option)
        if not all_views:
            raise LookupError("View with the specified name was not found.")
        view_item = all_views[0]

        # Step 3: Query the image endpoint and save the image to the specified location
        image_req_option = TSC.ImageRequestOptions(
            imageresolution=TSC.ImageRequestOptions.Resolution.High)
        server.views.populate_image(view_item, image_req_option)

        with open(args.filepath, "wb") as image_file:
            image_file.write(view_item.image)

        print("View image saved to {0}".format(args.filepath))
Ejemplo n.º 30
0
    def publish(self, creation_mode='CreateNew'):
        """Publishes a Hyper File to a Tableau Server"""

        # Ensure that the Hyper File exists
        if not os.path.isfile(self.hyper_file_path):
            error = "{0}: Hyper File not found".format(self.hyper_file_path)
            raise IOError(error)

        # Check the Hyper File size
        hyper_file_size = os.path.getsize(self.hyper_file_path)
        logging.info(f"The Hyper File size is (in bytes): {hyper_file_size}")

        username_pw_auth = TSC.TableauAuth(username=self.username, password=self.password, site_id=self.site_id)
        server = TSC.Server(self.tableau_server_url)
        server.use_server_version()
        with server.auth.sign_in(username_pw_auth):

            # Search for project on the Tableau server, filtering by project name
            req_options = TSC.RequestOptions()
            req_options.filter.add(TSC.Filter(TSC.RequestOptions.Field.Name,
                                              TSC.RequestOptions.Operator.Equals,
                                              self.project_name))
            projects, pagination = server.projects.get(req_options=req_options)
            for project in projects:
                if project.name == self.project_name:
                    logging.info(f'Found project on Tableau server. Project ID: {project.id}')
                    self.project_id = project.id

            # If project was not found on the Tableau Server, raise an error
            if self.project_id is None:
                raise ValueError(f'Invalid project name. Could not find project named "{self.project_name}" '
                                 f'on the Tableau server.')

            # Next, check if the datasource already exists and needs to be overwritten
            create_mode = TSC.Server.PublishMode.CreateNew
            if creation_mode.upper() == 'CREATENEW':

                # Search for the datasource under project name
                req_options = TSC.RequestOptions()
                req_options.filter.add(TSC.Filter(TSC.RequestOptions.Field.ProjectName,
                                                  TSC.RequestOptions.Operator.Equals,
                                                  self.project_name))
                req_options.filter.add(TSC.Filter(TSC.RequestOptions.Field.Name,
                                                  TSC.RequestOptions.Operator.Equals,
                                                  self.datasource_name))
                datasources, pagination = server.datasources.get(req_options=req_options)
                for datasource in datasources:
                    # the datasource already exists, overwrite
                    if datasource.name == self.datasource_name:
                        logging.info(f'Overwriting existing datasource named "{self.datasource_name}".')
                        create_mode = TSC.Server.PublishMode.Overwrite
                        break
            elif creation_mode.upper() == 'APPEND':
                create_mode = TSC.Server.PublishMode.Append
            else:
                raise ValueError(f'Invalid "creation_mode" : {creation_mode}')

            # Finally, publish the Hyper File to the Tableau server
            logging.info(f'Publishing Hyper File located at: "{self.hyper_file_path}"')
            logging.info(f'Create mode: {create_mode}')
            datasource_item = TSC.DatasourceItem(project_id=self.project_id, name=self.datasource_name)
            logging.info(f'Publishing datasource: \n{datasource_to_string(datasource_item)}')
            datasource_item = server.datasources.publish(datasource_item,
                                                         self.hyper_file_path,
                                                         create_mode)
            self.datasource_luid = datasource_item.id
            logging.info(f'Published datasource to Tableau server. Datasource LUID : {self.datasource_luid}')

        logging.info("Done.")

        return self.datasource_luid