Tableau Migration SDK 5.1.1
  • Articles
  • Code Samples
  • Python API Reference
  • C# API Reference
Show / Hide Table of Contents
  • Filters
    • Filter projects by name
    • Filter users by SiteRole
    • Filter Custom Views by 'Shared' flag
  • Mappings
    • Username email
    • Rename projects
    • Change projects
  • Transformers
    • Add tags to content
    • Encrypt Extracts
    • Adjust 'Start At' to Scheduled Tasks
    • Change default users for Custom Views
    • Action URL XML Transformer
  • Post-Publish Hooks
    • Update permissions
  • Bulk Post-Publish Hooks
    • Bulk logging
  • Batch Migration Completed Hooks
    • Batch migration logging
  • Migration Action Completed Hooks
    • Migration action logging

Sample EmailDomainMapping

This example is for a hypothetical scenario where the Tableau Server usernames are the same as the user part of the email. It uses a configuration class to supply the email domain.

  • Python
  • C#

Mapping Class

from tableau_migration import(
    IUser,
    TableauCloudUsernameMappingBase,
    ContentMappingContext)


class EmailDomainMapping(TableauCloudUsernameMappingBase):
    def map(self, ctx: ContentMappingContext[IUser]) -> ContentMappingContext[IUser]:
        _email_domain: str = "@mycompany.com"
        
        _tableau_user_domain = ctx.mapped_location.parent()

        # Re-use an existing email if it already exists. 
        if ctx.content_item.email:
            return ctx.map_to(_tableau_user_domain.append(ctx.content_item.email))
        
        # Takes the existing username and appends the domain to build the email
        new_email = ctx.content_item.name + _email_domain
        return ctx.map_to(_tableau_user_domain.append(new_email))

Registration

Learn more.

See the line with with_tableau_cloud_usernames.

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'])) \
                .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'])) \
                .for_server_to_cloud() \
                .with_tableau_id_authentication_type() \
                # You can add authentication type mappings here      
                .with_tableau_cloud_usernames(EmailDomainMapping)

This uses a configuration class to supply the email domain.

Mapping Class


namespace Csharp.ExampleApplication.Hooks.Mappings
{
    /// <summary>
    /// Mapping that appends an email domain to a username.
    /// </summary>
    public class EmailDomainMapping :
        ContentMappingBase<IUser>, // Base class to build mappings for content types
        ITableauCloudUsernameMapping
    {

        private readonly string _domain;

        /// <summary>
        /// Creates a new <see cref="EmailDomainMapping"/> object.
        /// </summary>
        /// <param name="optionsProvider">The options for this Mapping.</param>
        public EmailDomainMapping(
            IMigrationPlanOptionsProvider<EmailDomainMappingOptions> optionsProvider, 
            ISharedResourcesLocalizer localizer,
            ILogger<EmailDomainMapping> logger) 
                : base(localizer, logger)
        {
            _domain = optionsProvider.Get().EmailDomain;
        }

        /// <summary>
        /// Adds an email to the user if it doesn't exist.
        /// This is where the main logic of the mapping should reside.
        /// </summary>
        public override Task<ContentMappingContext<IUser>?> MapAsync(ContentMappingContext<IUser> userMappingContext, CancellationToken cancel)
        {
            var domain = userMappingContext.MappedLocation.Parent();

            // Re-use an existing email if it already exists.
            if (!string.IsNullOrEmpty(userMappingContext.ContentItem.Email))
                return userMappingContext.MapTo(domain.Append(userMappingContext.ContentItem.Email)).ToTask();

            // Takes the existing username and appends the domain to build the email
            var testEmail = $"{userMappingContext.ContentItem.Name}@{_domain}";
            return userMappingContext.MapTo(domain.Append(testEmail)).ToTask();
        }
    }
}

Configuration Class

namespace Csharp.ExampleApplication.Hooks.Mappings
{
    public sealed class EmailDomainMappingOptions
    {
        public string EmailDomain { get; set; } = string.Empty;
    }
}

Registration

Learn more.

See the line with WithTableauCloudUsernames.

// Use the methods on your plan builder to add configuration and make customizations.
_planBuilder = _planBuilder
    .FromSourceTableauServer(_options.Source.ServerUrl, _options.Source.SiteContentUrl, _options.Source.AccessTokenName, Environment.GetEnvironmentVariable("TABLEAU_MIGRATION_SOURCE_TOKEN") ?? string.Empty)
    .ToDestinationTableauCloud(_options.Destination.ServerUrl, _options.Destination.SiteContentUrl, _options.Destination.AccessTokenName, Environment.GetEnvironmentVariable("TABLEAU_MIGRATION_DESTINATION_TOKEN") ?? string.Empty)
    .ForServerToCloud()
    .WithTableauIdAuthenticationType()
    // You can add authentication type mappings here            
    .WithTableauCloudUsernames<EmailDomainMapping>();

Dependency Injection

Learn more.

services.AddScoped<EmailDomainMapping>();
  • Edit this page
In this article