tableau-api

tableauserverclient update a connection that is currently oauth to user+password


using TSC to update credentials of snowflake connections in tableau workbooks, like this:

enter cowb = server.workbooks.get_by_id('yyyyyyy-yyyyy-yyyy-yyyyy-yyyyyyy')
server.workbooks.populate_connections(wb)
connection = wb.connections[0]
connection.username = 'TABLEAU_USER'
connection.password = 'tb_pass'
connection.embed_password=True
server.workbooks.update_connection(wb, connection)

this works fine for workbooks connecting currently using user+pass and it changes the name and the password, but when I try to do that to connection that is currently an oauth connection, I get:

404020: Resource Not Found
    Cannot find data connection 'xxxxxx-xxxx-xxxxx-xxxxx-xxxxxx' for datasource 'yyyyyy-yyyy-yyyy-yyyy-yyyyyyyyy'.

any ideas how to notify the api I want to ditch oauth and use user+pass instead?


Solution

  • Tableau connection data is stored in the workbook's XML, this also includes HOW a user authenticates to a datasource.

    The way the user connects determines how Tableau expects all connections for that content to be (at least until it has been changed in the workbook's XML). This is why republishing from desktop to update connections works but is not always in the case via the API; the xml is updated with the new auth method when the desktop workbook is republished.

    neozenith has a fantastic explanation and solution to this problem on github.

    I managed to get publishing updated credentials working via this method:

    • server.datasources.download()
    • server.datasources.publish()

    It even overwrote OAuth connection detail credentials with the fixed username/password I was applying to all datasources selected.

    ...

    for datasource in datasources:
           print(datasource.name)
           # Retrieve connection details.
          server.datasources.populate_connections(datasource)
    
           # Downloaded Datasource Document (.tdsx file)
           downloaded_datasource = server.datasources.download(datasource.id, include_extract=False)
           print(downloaded_datasource)
    
           # Publish an updated version and Overwrite with new credentials
           updated_datasource = server.datasources.publish(
               datasource_item=datasource,
               file=Path(downloaded_datasource),
               mode=TSC.Server.PublishMode.Overwrite,
               connection_credentials=TSC.ConnectionCredentials(
                   os.environ.get("CREDENTIAL_USERNAME"), 
                   os.environ.get("NEW_PASSWORD"),
                   embed=True, 
                   oauth=False
               ),
    

    NOTE: Added this code snippet above for reference/ conciseness for this SO answer, as this question is not on this site. It is not my code, source here.