Tableau Migration SDK 5.1.1
  • Articles
  • Code Samples
  • Python API Reference
  • C# API Reference
Show / Hide Table of Contents
  • tableau_migration
    • migration
      • get_service
      • get_service_provider
      • PyMigrationResult
      • PyMigrationManifest
      • PyMigrationCompletionStatus
      • PyContentReference
      • PyContentLocation
      • PyPipelineProfile
      • PyResult
    • migration_api_rest
      • PyRestIdentifiable
    • migration_api_rest_models
      • PyAdministratorLevels
      • PyContentPermissions
      • PyLabelCategories
      • PyLicenseLevels
      • PyPermissionsCapabilityModes
      • PyPermissionsCapabilityNames
      • PySiteRoles
      • PyExtractEncryptionModes
    • migration_api_rest_models_types
      • PyAuthenticationTypes
      • PyDataSourceFileTypes
      • PyWorkbookFileTypes
    • migration_content
      • PyCloudSubscription
      • PySubscription
      • PySubscriptionContent
      • PyTag
      • PyUser
      • PyUserAuthenticationType
      • PyUsernameContent
      • PyServerSubscription
      • PyView
      • PyWithOwner
      • PyWithTags
      • PyWithWorkbook
      • PyWorkbook
      • PyWorkbookDetails
      • PyWithDomain
      • PyPublishedContent
      • PyPublishableGroup
      • PyConnection
      • PyConnectionsContent
      • PyContainerContent
      • PyCustomView
      • PyDataSource
      • PyDataSourceDetails
      • PyPublishableWorkbook
      • PyDescriptionContent
      • PyGroup
      • PyGroupUser
      • PyLabel
      • PyProject
      • PyPublishableCustomView
      • PyPublishableDataSource
      • PyExtractContent
    • migration_content_permissions
      • PyPermissions
      • PyGranteeType
      • PyGranteeCapability
      • PyCapability
    • migration_content_schedules
      • PyInterval
      • PyFrequencyDetails
      • PyExtractRefreshTask
      • PyExtractRefreshContentType
      • PySchedule
      • PyWithSchedule
    • migration_content_schedules_cloud
      • PyCloudSchedule
      • PyCloudExtractRefreshTask
    • migration_content_schedules_server
      • PyServerSchedule
      • PyServerExtractRefreshTask
    • migration_engine
      • PyServerToCloudMigrationPlanBuilder
      • PyMigrationPlanBuilder
      • PyMigrationPlan
      • PyContentMigrationItem
    • migration_engine_actions
      • PyMigrationActionResult
    • migration_engine_endpoints_search
      • PySourceContentReferenceFinder
      • PySourceContentReferenceFinderFactory
      • PyDestinationContentReferenceFinderFactory
      • PyDestinationContentReferenceFinder
    • migration_engine_hooks
      • PyMigrationHookBuilder
      • PyMigrationHookFactoryCollection
    • migration_engine_hooks_filters
      • PyContentFilterBuilder
    • migration_engine_hooks_filters_interop
      • PyContentFilterBase
    • migration_engine_hooks_interop
      • PyInitializeMigrationHookBase
      • PyMigrationActionCompletedHookBase
      • PyContentBatchMigrationCompletedHookBase
    • migration_engine_hooks_mappings
      • PyContentMappingContext
      • PyContentMappingBuilder
    • migration_engine_hooks_mappings_interop
      • PyContentMappingBase
      • PyTableauCloudUsernameMappingBase
    • migration_engine_hooks_postpublish
      • PyContentItemPostPublishContext
      • PyBulkPostPublishContext
    • migration_engine_hooks_postpublish_interop
      • PyContentItemPostPublishHookBase
      • PyBulkPostPublishHookBase
    • migration_engine_hooks_results
      • PyInitializeMigrationHookResult
    • migration_engine_hooks_transformers
      • PyContentTransformerBuilder
    • migration_engine_hooks_transformers_interop
      • PyXmlContentTransformerBase
      • PyContentTransformerBase
    • migration_engine_manifest
      • PyMigrationManifestEntryEditor
      • PyMigrationManifestEntryStatus
      • PyMigrationManifestSerializer
      • PyMigrationManifestEntry
    • migration_engine_migrators
      • PyContentItemMigrationResult
      • PyMigrator
    • migration_engine_migrators_batch
      • PyContentBatchMigrationResult
    • migration_engine_options
      • PyMigrationPlanOptionsBuilder
      • PyMigrationPlanOptionsCollection
    • migration_engine_pipelines
      • PyMigrationPipelineContentType
      • PyServerToCloudMigrationPipeline
    • migration_enum
    • migration_logger
      • MigrationLogger
    • migration_services
      • ScopedMigrationServices

Introduction

Welcome to the Python API Reference for the Migration SDK.

The Migration SDK is written in .NET. It has a Python wrapper package that provides access to most of this functionality.

Capabilities

With the Python API, you can:

  • Provide basic configuration values to the Migration SDK via the PlanBuilder.
  • Set configuration options as described in Configuration with environment variables.
  • Configure Python logging.
  • Run a migration using python.
  • Write Python hooks. See Custom Hooks for an overview.

Current limitations

There are advanced features of the Migration SDK that the Python Wrapper cannot currently access:

  • Override C# classes and methods to change how the SDK works.

Examples to get started

The following code samples are for writing a simple migration app using the Migration SDK. For details on configuring and customizing the Migration SDK to your specific needs, see Articles and Code Samples.

  • Startup Scripts
  • config.ini
  • requirements.txt

Main module:

# This application performs a basic migration using the Tableau Migration SDK.
# By default all supported content will be migrated, but can be modified to your specific needs.
# The application assumes you have already installed the Tableau Migration SDK Python package.

from dotenv import load_dotenv

load_dotenv()

import configparser          # configuration parser
import os                    # environment variables
import tableau_migration     # Tableau Migration SDK
from print_result import print_result

from threading import Thread # threading

from tableau_migration import (
    MigrationManifestSerializer,
    MigrationManifest
)

serializer = MigrationManifestSerializer()

def migrate():
    """Performs a migration using Tableau Migration SDK."""
    
    # Get the absolute path of the current file
    current_file_path = os.path.abspath(__file__)
    manifest_path = os.path.join(os.path.dirname(current_file_path), 'manifest.json')

    plan_builder = tableau_migration.MigrationPlanBuilder()
    migration = tableau_migration.Migrator()

    config = configparser.ConfigParser()
    config.read('config.ini')

    # Build the plan.
    plan_builder = 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 = os.environ.get('TABLEAU_MIGRATION_SOURCE_TOKEN', config['SOURCE']['ACCESS_TOKEN']),
                        create_api_simulator = os.environ.get('TABLEAU_MIGRATION_SOURCE_SIMULATION', 'False') == 'True') \
                    .to_destination_tableau_cloud(
                        pod_url = config['DESTINATION']['URL'], 
                        site_content_url = config['DESTINATION']['SITE_CONTENT_URL'], 
                        access_token_name = config['DESTINATION']['ACCESS_TOKEN_NAME'], 
                        access_token = os.environ.get('TABLEAU_MIGRATION_DESTINATION_TOKEN', config['DESTINATION']['ACCESS_TOKEN']),
                        create_api_simulator = os.environ.get('TABLEAU_MIGRATION_DESTINATION_SIMULATION', 'False') == 'True') \
                    .for_server_to_cloud() \
                    .with_tableau_id_authentication_type() \
                    .with_tableau_cloud_usernames(config['USERS']['EMAIL_DOMAIN'])                    

    # TODO: add filters, mappings, transformers, etc. here.


    # Load the previous manifest file if it exists.
    prev_manifest = load_manifest(f'{manifest_path}')

    # Validate the migration plan.
    validation_result = plan_builder.validate()

    # TODO: Handle errors if the validation fails here.

    plan = plan_builder.build()

    # Run the migration.
    results = migration.execute(plan, prev_manifest)
    
    # Save the manifest file.
    serializer.save(results.manifest, f'{manifest_path}')

    # TODO: Handle results here.
    print_result(results)

    print("All done.")

def load_manifest(manifest_path: str) -> MigrationManifest | None:
        """Loads a manifest if requested."""
        manifest = serializer.load(manifest_path)
    
        if manifest is not None:
            while True:
                answer = input(f'Existing Manifest found at {manifest_path}. Should it be used? [Y/n] ').upper()

                if answer == 'N':
                    return None
                elif answer == 'Y' or answer == '':
                    return manifest
                
        return None
    

if __name__ == '__main__':
    
    # Create a thread that will run the migration and start it.
    migration_thread = Thread(target = migrate)
    migration_thread.start()
    done = False

    # Create a busy-wait loop to continue checking if Ctrl+C was pressed to cancel the migration.
    while not done:
        try:
            migration_thread.join(1)
            done = True
        except KeyboardInterrupt:
            # Ctrl+C was caught, request migration to cancel. 
            print("Caught Ctrl+C, shutting down...")
            
            # This will cause the Migration SDK to cleanup and finish,
            # which will cause the thread to finish.
            tableau_migration.cancellation_token_source.Cancel()
            
            # Wait for the migration thread to finish and then quit the application.
            migration_thread.join()
            done = True

print_result helper module:

from tableau_migration import (
    IMigrationManifestEntry, 
    MigrationManifestEntryStatus, 
    MigrationResult,
    ServerToCloudMigrationPipeline
)

def print_result(result: MigrationResult):
        """Prints the result of a migration."""
        print(f'Result: {result.status}')
    
        for pipeline_content_type in ServerToCloudMigrationPipeline.get_content_types():
            content_type = pipeline_content_type.content_type
            
            type_entries = [IMigrationManifestEntry(x) for x in result.manifest.entries.ForContentType(content_type)]
        
            count_total = len(type_entries)

            count_migrated = 0
            count_skipped = 0
            count_errored = 0
            count_cancelled = 0
            count_pending = 0

            for entry in type_entries:
                if entry.status == MigrationManifestEntryStatus.MIGRATED:
                    count_migrated += 1
                elif entry.status == MigrationManifestEntryStatus.SKIPPED:
                    count_skipped += 1
                elif entry.status == MigrationManifestEntryStatus.ERROR:
                    count_errored += 1
                elif entry.status == MigrationManifestEntryStatus.CANCELED:
                    count_cancelled += 1
                elif entry.status == MigrationManifestEntryStatus.PENDING:
                    count_pending += 1
            
            output = f'''
            {content_type.Name}
            \t{count_migrated}/{count_total} succeeded
            \t{count_skipped}/{count_total} skipped
            \t{count_errored}/{count_total} errored
            \t{count_cancelled}/{count_total} cancelled
            \t{count_pending}/{count_total} pending
            '''
               
            print(output)
Important

The values below should not be quoted. So no ' or ".

[SOURCE]
URL = http://server
SITE_CONTENT_URL = 
ACCESS_TOKEN_NAME = MyServerTokenName
ACCESS_TOKEN = 

[DESTINATION]
URL = https://pod.online.tableau.com
SITE_CONTENT_URL = mycloudsite
ACCESS_TOKEN_NAME = MyCloudTokenName
ACCESS_TOKEN = 

[USERS]
EMAIL_DOMAIN = mycompany.com
python-dotenv==1.0.1
In this article