I'm encountering a "SignIn Error" while attempting to migrate from an on-premises Tableau server to Tableau Online using a personal access token (PAT). I suspect the issue might be related to the URL or site content URL configuration.
import tableau_migration
import os
from dotenv import load_dotenv
import configparser
from tableau_migration.migration_engine import PyMigrationPlanBuilder
from tableau_migration.migration_engine_migrators import PyMigrator
from threading import Thread
load_dotenv()
# Access environment variables
on_prem_token_name = os.environ.get("on_prem_token_name")
on_prem_private_token = os.environ.get("on_prem_private_token")
cloud_token_name = os.environ.get("cloud_token_name")
cloud_private_token = os.environ.get("cloud_private_token")
# Read configuration from config.ini
config = configparser.ConfigParser()
config.read('config.ini')
# Output all the inputs read by the config reader
for section in config.sections():
print(f"Section: {section}")
for option in config.options(section):
value = config.get(section, option)
first_three_letters = value[:3] if len(value) >= 3 else value
print(f" Option: {option}, Value: {first_three_letters}, Len: {len(value)}")
def migrate_single_workbook():
# Initialize migration plan builder and migrator
plan_builder = PyMigrationPlanBuilder()
migrator = PyMigrator()
# Read configuration from config.ini
config = configparser.ConfigParser()
config.read('config.ini')
# Build the migration plan
plan = plan_builder \
.from_source_tableau_server(
server_url=config['SOURCE']['URL'],
site_content_url=config['SOURCE']['SITE_CONTENT_URL'],
access_token_name=config['SOURCE']['ACCESS_TOKEN_NAME'],
access_token=on_prem_private_token)\
.to_destination_tableau_cloud(
pod_url=config['DESTINATION']['URL'],
site_content_url=config['SOURCE']['SITE_CONTENT_URL'],
access_token_name=config['DESTINATION']['ACCESS_TOKEN_NAME'],
access_token=cloud_private_token
) \
.for_server_to_cloud() \
.with_tableau_id_authentication_type() \
.with_tableau_cloud_usernames(config['USERS']['EMAIL_DOMAIN']) \
.build()
# Execute the migration plan
results = migrator.execute(plan)
# Handle migration results
for result in results:
print(result)
return plan
# Create a thread to run the migration
migration_thread = Thread(target=migrate_single_workbook)
migration_thread.start()
# Wait for the migration to complete or handle interruption
while True:
try:
migration_thread.join(1)
break
except KeyboardInterrupt:
print("Migration interrupted. Cleaning up...")
# Cleanup resources if needed
break
Error Message:
An error occurred during migration. Error: Tableau.Migration.Api.Rest.RestException: An error was returned from the Tableau API:
URL: <both websites throwing the same error>
Code: 401001
Summary: Signin Error
Detail: Error signing in to Tableau Server
Environment:
- Python 3.11.5
- Running on an AWS cloud VM
Additional Details: I've verified that the personal access token (PAT) and other environment variables are correctly set up by printing them out. However, I suspect that the issue might be related to the URL or site content URL configuration in my config.ini file (tried various variants).
[SOURCE]
URL = https://tableau.website.com/
SITE_CONTENT_URL = #/site/projects/87
ACCESS_TOKEN_NAME = access_token_name
[DESTINATION]
URL = https://prod-us-b.online.tableau.com/#/site/tableaucompanywebsite
SITE_CONTENT_URL =
ACCESS_TOKEN_NAME = cloud_access_token_name
[USERS]
EMAIL_DOMAIN = company.com
Request for Assistance:
I'm unsure about the correctness of the URL and site content URL configurations, especially considering the naming convention that includes a '#' in the URL. Overall, unsure about the code or process in general after reading the docs. I suspect that I don't have the SITE_CONTENT_URL correct, but I'm not sure how to resolve the 'SignIn Error'. Any guidance on troubleshooting or correcting these configurations would be greatly appreciated.
The issue is the URLs and the environment variables you are setting.
The config.ini should be something like
Set the below environment variables for tokens (instead of
on_prem_private_token
andcloud_private_token
). Remember they need to be set before you run the Python script.TABLEAU_MIGRATION_DESTINATION_TOKEN
TABLEAU_MIGRATION_DESTINATION_TOKEN
You can follow the code on Github for guidance. That code uses json based config for the stuff other than the tokens but you don't have to do that.