tableau / server-client-python

A Python library for the Tableau Server REST API
https://tableau.github.io/server-client-python/
MIT License
659 stars 421 forks source link

Issue publishing one workbook but not others #1139

Closed cmbramwell closed 2 months ago

cmbramwell commented 2 years ago

I'm trying to publish a set of workbooks via the Tableau Server Client. All of the workbooks that I'm publishing are working perfectly as expected except for one. The workbook that is not publishing correctly is connected to three separate published data sources. The other workbooks that are publishing correctly are connected to a variety of published and live data sources.

Versions

To Reproduce

upload_dF = pd.read_excel(fullpath + 'Tableau Input.xlsx', sheet_name='Upload')

for row in upload_dF.itertuples():

    server_name = row.server
    project_id = row.project_id
    name = row.name
    workbook_path = row.filepath

    config = tableau_config[server_name]

    tableau_auth = TSC.PersonalAccessTokenAuth(
        config['personal_access_token_name'],
        config['personal_access_token_secret'],
        site_id=config['site_name'])
    server = TSC.Server(config['server'], use_server_version=True)

    with server.auth.sign_in(tableau_auth):

        print(server_name + '-' + name)

        connection_credentials = TSC.ConnectionCredentials(
            conn_username,
            conn_password,
            embed=True,
            oauth=True)

        WorkbookItem = TSC.WorkbookItem(
            name=name,
            project_id=project_id,
            show_tabs=True
        )

        try:

            new_workbook = server.workbooks.publish(
                WorkbookItem,
                workbook_path,
                mode='Overwrite',
                # connections=dest_connections,
                connection_credentials=connection_credentials,
                skip_connection_check=True,
                as_job=False
            )
            print('Published Destination Connections')

        except:
            new_workbook = server.workbooks.publish(
                WorkbookItem,
                workbook_path,
                mode='Overwrite',
                connections=None,
                skip_connection_check=True,
                as_job=False
            )
            print('Published without Destination Connections')

        print("Successfully published {0} ({1})".format(new_workbook.name, new_workbook.id))

Results

tableauserverclient.server.endpoint.exceptions.ServerResponseError: 

    500000: Forbidden
        User does not have permission for action.(The server encountered an error and cannot complete your request. Contact your server administrator.)

I am the site administrator and I have full admin access to all properties on the site.

jacalata commented 2 years ago

That is an unusual error code. Just to check: have you been able to publish this workbook manually? Have you tried publishing a workbook with connections to each of the datasources individually?

cmbramwell commented 2 years ago

@jacalata Yes, I can publish the workbook manually.

As of an hour ago, I tried using the script to publish the workbook with different combinations of the data sources. I found one data source in the workbook that was causing the issue. I created a local copy of that data source. I then published the workbook with the two published data sources and one extract of the local copy. It worked.

I then tried creating a live version of the local copy, and it would not publish.

Any idea what may be causing this to throw an error for this one published data sources?

jacalata commented 2 years ago

Hm, it's hitting a problem when it tries to verify the embedded credentials to the published datasource. Is it possible this datasource is not OAuth and your other datasources are? Or is there anything else that is different about this one?

It sounds like it might be related to this gap in the API: "Note: Even if credentials are embedded in a workbook, you must still provide credentials when connecting to a data source that requires credentials, unless that data source uses OAuth." https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref.htm#publish_workbook

rkg5142 commented 2 years ago

Hello, same issue for me - also a server admin with full permissions to everything.

Some workbooks can publish fine, while others return: 500000: Forbidden User does not have permission for action.(The server encountered an error and cannot complete your request. Contact your server administrator.)

The strange thing is, the data source and creds are identical between failing and successfully published workbooks.

rkg5142 commented 2 years ago

Hello, same issue for me - also a server admin with full permissions to everything.

Some workbooks can publish fine, while others return: 500000: Forbidden User does not have permission for action.(The server encountered an error and cannot complete your request. Contact your server administrator.)

The strange thing is, the data source and creds are identical between failing and successfully published workbooks.

If this is helpful, for your investigation, in my instance, I am using TSC to download a workbook, the document API to modify datasource connection info, and re-publishing the workbook using TSC. The change I made to my code which introduces this error was updating datasources.caption. If I remove this line, I can publish all workbooks fine - so likely is an issue with the value I was using for the field (AKA maybe a user error on my end).

nosnilmot commented 1 year ago

I'm seeing similar problems.

I can only successfully publish a workbook if I specify connections=None and skip_connection_check=False in the server.workbooks.publish() parameters.

If I specify connections=None and skip_connection_check=True I get the 500000 error reported here.

If I specify connections I see a variety of different errors (400011, 403132, Internal error 500) for different combinations values of connections and skip_connection_check

I might be able to proceed with connections=None and skip_connection_check=False but that feels wrong. It is also very confusing that the errors occur more when connection check is disabled.

I'm using Tableau Server 2022.3 and can provide logs from server-side for failing API requests if it would be helpful.

nosnilmot commented 1 year ago

I have solved (some of?) my problems, maybe these can help others too:

  1. If an empty list is provided to connections, Tableau Server reports 500000 error, solution is to pass connections=None instead

  2. If passing a list of ConnectionInfo items in connections, they must have ConnectionCredenials set in connection_credentials attribute. Without this, Internal error 500 is reported. It is not sufficient to set username/password/embed_password attributes of the ConnectionInfo class. This was not at all obvious because the documentation at https://tableau.github.io/server-client-python/docs/api-ref#connections does not even indicate there is a connection_credentials attribute of ConnectionInfo!

  3. Sometimes it just helps to use the correct username and password

jacalata commented 1 year ago

@cmbramwell I think I ended up addressing the new issues people brought up, but not yours. Did anything here help, or did you figure it out yourself?

bryceglarsen commented 6 months ago

We recently encountered this issue on Server Version 2023.3. We had no issues until this server upgrade and our original use of skip_connections_check=True now results in generic 400011: Bad Request.

I can open a new issue, but waiting for logs from admin to verify further.

Removing the skip connections check allows us to publish successfully.