Skip to content

Commit

Permalink
Release 4.3.0
Browse files Browse the repository at this point in the history
  • Loading branch information
pvshn committed Sep 3, 2024
1 parent 7fdba58 commit ea65ff2
Show file tree
Hide file tree
Showing 229 changed files with 8,970 additions and 1,349 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/dotnet-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ jobs:
run: dotnet build '${{ vars.BUILD_SOLUTION }}' -c ${{ matrix.config }}
- name: Test solution with ${{ matrix.config }} configuration
run: |
dotnet test '${{ vars.BUILD_SOLUTION }}' --no-build -c ${{ matrix.config }} --verbosity normal --logger trx --results-directory "TestResults-${{ matrix.os }}-${{ matrix.config }}" -- RunConfiguration.TestSessionTimeout=${{ vars.MIGRATIONSDK_TEST_CANCELLATION_TIMEOUT_MILLISECONDS }}
dotnet test '${{ vars.BUILD_SOLUTION }}' --no-build -c ${{ matrix.config }} --verbosity normal --logger junit --results-directory "TestResults-${{ matrix.os }}-${{ matrix.config }}" -- RunConfiguration.TestSessionTimeout=${{ vars.MIGRATIONSDK_TEST_CANCELLATION_TIMEOUT_MILLISECONDS }}
- name: Upload test results
# Use always() to always run this step to publish test results when there are test failures
if: ${{ always() }}
uses: actions/upload-artifact@v4
with:
name: dotnet-results-${{ matrix.os }}-${{ matrix.config }}
path: TestResults-${{ matrix.os }}-${{ matrix.config }}
if-no-files-found: error
if-no-files-found: error
10 changes: 0 additions & 10 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,6 @@ instance/
# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
.pybuilder/
Expand Down Expand Up @@ -179,14 +177,6 @@ launchSettings.json
UpgradeLog.htm
*.*.ini
*.*.json
/src/Python/Documentation/_build
/src/Python/Documentation/_static
/src/Python/Python.pyproj.user
/src/Documentation/_python
/src/Python/Documentation/generated
/tests/Python.TestApplication/manifest.json
/.git2gus
/src/Python/scripts/publish-package.ps1

# Public repo ignores
.github/pull_request_template.md
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<Nullable>enable</Nullable>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<Version>4.2.0</Version>
<Version>4.3.0</Version>
<Authors>Salesforce, Inc.</Authors>
<Company>Salesforce, Inc.</Company>
<Copyright>Copyright (c) 2024, Salesforce, Inc. and its licensors</Copyright>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System;
using Microsoft.Extensions.Logging;
using Tableau.Migration.Api.Rest.Models;
using Tableau.Migration.Content;
using Tableau.Migration.Engine;
using Tableau.Migration.Engine.Hooks.Filters;
using Tableau.Migration.Resources;

namespace Csharp.ExampleApplication.Hooks.Filters
{
#region class
public class SharedCustomViewFilter : ContentFilterBase<ICustomView>
{
public SharedCustomViewFilter(
ISharedResourcesLocalizer localizer,
ILogger<IContentFilter<ICustomView>> logger)
: base(localizer, logger) { }

public override bool ShouldMigrate(ContentMigrationItem<ICustomView> item)
{
return !item.SourceItem.Shared;
}
}
#endregion
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Tableau.Migration;
using Tableau.Migration.Content;
using Tableau.Migration.Engine.Hooks.Transformers;
using Tableau.Migration.Resources;

namespace Csharp.ExampleApplication.Hooks.Transformers
{
#region class
public class CustomViewExcludeDefaultUserTransformer(
ISharedResourcesLocalizer localizer,
ILogger<CustomViewExcludeDefaultUserTransformer> logger)
: ContentTransformerBase<IPublishableCustomView>(localizer, logger)
{
public IList<string> ExcludeUsernames { get; } = new List<string>() {"User1", "User2"};


private readonly ILogger<CustomViewExcludeDefaultUserTransformer>? _logger = logger;

public override async Task<IPublishableCustomView?> TransformAsync(IPublishableCustomView itemToTransform, CancellationToken cancel)
{
var newDefaultUsers = itemToTransform.DefaultUsers.Where(user => !ExcludeUsernames.Contains(user.Name)).ToList();

itemToTransform.DefaultUsers = newDefaultUsers;

_logger?.LogInformation(
@"Excluding default users {newDefaultUsers}",
newDefaultUsers);

return await Task.FromResult(itemToTransform);
}
}
#endregion
}
8 changes: 8 additions & 0 deletions examples/Csharp.ExampleApplication/MyMigrationApplication.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ public async Task StartAsync(CancellationToken cancel)
#region UnlicensedUsersFilter-Registration
_planBuilder.Filters.Add<UnlicensedUsersFilter, IUser>();
#endregion

#region SharedCustomViewFilter-Registration
_planBuilder.Filters.Add<SharedCustomViewFilter, ICustomView>();
#endregion

// Add post-publish hooks
#region UpdatePermissionsHook-Registration
Expand All @@ -138,6 +142,10 @@ public async Task StartAsync(CancellationToken cancel)
#region StartAtTransformer-Registration
_planBuilder.Transformers.Add<SimpleScheduleStartAtTransformer<ICloudExtractRefreshTask>, ICloudExtractRefreshTask>();
#endregion

#region CustomViewDefaultUsersTransformer-Registration
_planBuilder.Transformers.Add<CustomViewExcludeDefaultUserTransformer, IPublishableCustomView>();
#endregion

// Add migration action completed hooks
#region LogMigrationActionsHook-Registration
Expand Down
8 changes: 8 additions & 0 deletions examples/Csharp.ExampleApplication/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ public static IServiceCollection AddCustomizations(this IServiceCollection servi
#region UnlicensedUsersFilter-DI
services.AddScoped<UnlicensedUsersFilter>();
#endregion

#region SharedCustomViewFilter-DI
services.AddScoped<SharedCustomViewFilter>();
#endregion

#region UpdatePermissionsHook-DI
services.AddScoped(typeof(UpdatePermissionsHook<,>));
Expand All @@ -90,6 +94,10 @@ public static IServiceCollection AddCustomizations(this IServiceCollection servi
#region StartAtTransformer-DI
services.AddScoped(typeof(SimpleScheduleStartAtTransformer<>));
#endregion

#region CustomViewDefaultUsersTransformer-DI
services.AddScoped<CustomViewExcludeDefaultUserTransformer>();
#endregion

#region LogMigrationActionsHook-DI
services.AddScoped<LogMigrationActionsHook>();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from tableau_migration import (
ICustomView,
ContentMigrationItem,
ContentFilterBase)


class SharedCustomViewFilter(ContentFilterBase[ICustomView]):
def should_migrate(self, item: ContentMigrationItem[ICustomView]) -> bool:
if item.source_item.shared == True:
return False
return True
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ def map(self, ctx: ContentMappingContext[IProject]) -> ContentMappingContext[IPr

new_location = ctx.content_item.location.rename("Production")

ctx.map_to(new_location)
ctx = ctx.map_to(new_location)

return ctx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from tableau_migration import (
ContentTransformerBase,
IContentReference,
IPublishableCustomView
)

class CustomViewDefaultUsersTransformer(ContentTransformerBase[IPublishableCustomView]):

#Pass in list of users retrieved from Users API
default_users = []

def transform(self, itemToTransform: IPublishableCustomView) -> IPublishableCustomView:
itemToTransform.default_users = self.default_users
return itemToTransform
13 changes: 7 additions & 6 deletions examples/Python.ExampleApplication/Python.ExampleApplication.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,15 @@

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

from threading import Thread # threading

from tableau_migration import (
MigrationManifestSerializer,
MigrationManifest
)
)

serializer = MigrationManifestSerializer()

Expand All @@ -40,12 +39,14 @@ def migrate():
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'])) \
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'])) \
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'])
Expand Down Expand Up @@ -101,7 +102,7 @@ def load_manifest(manifest_path: str) -> MigrationManifest | None:
while not done:
try:
migration_thread.join(1)
sys.exit(0)
done = True
except KeyboardInterrupt:
# Ctrl+C was caught, request migration to cancel.
print("Caught Ctrl+C, shutting down...")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,15 @@
<Compile Include="hooks\mappings\project_rename_mapping.py" />
<Compile Include="hooks\migration_action_completed\log_migration_actions_hook.py" />
<Compile Include="hooks\post_publish\bulk_logging_hook.py" />
<Compile Include="Hooks\transformers\custom_view_default_users_transformer.py" />
<Compile Include="hooks\transformers\encrypt_extracts_transformer.py" />
<Compile Include="hooks\transformers\migrated_tag_transformer.py" />
<Compile Include="Hooks\transformers\schedule_startat_transformer.py" />
<Compile Include="print_result.py" />
<Compile Include="Python.ExampleApplication.py" />
</ItemGroup>
<ItemGroup>
<Content Include=".env" />
<Content Include="config*.ini" />
<Content Include="pyproject.toml" />
<Content Include="requirements.txt" />
Expand Down
2 changes: 2 additions & 0 deletions examples/Python.ExampleApplication/config.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
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
7 changes: 3 additions & 4 deletions examples/Python.ExampleApplication/print_result.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import tableau_migration
from tableau_migration.migration import PyMigrationResult
from tableau_migration import IMigrationManifestEntry, MigrationManifestEntryStatus
from Tableau.Migration.Engine.Pipelines import ServerToCloudMigrationPipeline

def print_result(self, result: PyMigrationResult):
def print_result(result: PyMigrationResult):
"""Prints the result of a migration."""
self.logger.info(f'Result: {result.status}')
print(f'Result: {result.status}')

for pipeline_content_type in ServerToCloudMigrationPipeline.ContentTypes:
content_type = pipeline_content_type.ContentType
Expand Down Expand Up @@ -41,4 +40,4 @@ def print_result(self, result: PyMigrationResult):
\t{count_pending}/{count_total} pending
'''

self.logger.info(output)
print(output)
5 changes: 0 additions & 5 deletions examples/Python.ExampleApplication/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
setuptools==70.1.1
configparser==7.0.0
tableau_migration
cffi==1.16.0
pycparser==2.22
pythonnet==3.0.3
typing_extensions==4.12.2
python-dotenv==1.0.1
35 changes: 1 addition & 34 deletions src/Documentation/api-csharp/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,40 +6,7 @@ Welcome to the C# API Reference for the Migration SDK.

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](~/articles/index.md) and [Code Samples](~/samples/index.md).

### [Program.cs](#tab/program-cs)

[!code-csharp[](../../../examples/Csharp.ExampleApplication/Program.cs#namespace)]

### [Startup code](#tab/startup-cde)

[!code-csharp[](../../../examples/Csharp.ExampleApplication/MyMigrationApplication.cs#namespace)]

### [Config classes](#tab/config-classes)

[!code-csharp[](../../../examples/Csharp.ExampleApplication/Config/MyMigrationApplicationOptions.cs#namespace)]

[!code-csharp[](../../../examples/Csharp.ExampleApplication/Config/EndpointOptions.cs#namespace)]

### [Config file](#tab/appsettings)

```json
{
"source": {
"serverUrl": "http://server",
"siteContentUrl": "",
"accessTokenName": "my server token name",
"accessToken": "my-secret-server-pat"
},
"destination": {
"serverUrl": "https://pod.online.tableau.com",
"siteContentUrl": "site-name",
"accessTokenName": "my cloud token name",
"accessToken": "my-secret-cloud-pat"
}
}
```

---
[!include[](~/includes/csharp-getting-started.md)]

## Suggested Reading

Expand Down
17 changes: 1 addition & 16 deletions src/Documentation/api-python/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,4 @@ There are advanced features of the Migration SDK that the Python Wrapper cannot

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](~/articles/index.md) and [Code Samples](~/samples/index.md).

### [Startup Script](#tab/startup)

[!code-python[](../../../examples/Python.ExampleApplication/Python.ExampleApplication.py)]

### [config.ini](#tab/config)

> [!Important]
> The values below should not be quoted. So ***no*** `'` or `"`.
[!code-ini[](../../../examples/Python.ExampleApplication/config.ini)]

### [requirements.txt](#tab/reqs)

[!code-text[](../../../examples/Python.ExampleApplication/requirements.txt#L3-)]

---
[!include[](~/includes/python-getting-started.md)]
14 changes: 14 additions & 0 deletions src/Documentation/articles/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,20 @@ Supported Content Types:

*Description:* The Migration SDK uses [Microsoft.Extensions.Http.Resilience](https://learn.microsoft.com/en-us/dotnet/core/resilience) as a resilience and transient-fault layer. The SDK uses the **PerFileTransferRequestTimeout** property to define the maximum duration of FileTransfer requests.


### Network.UserAgentComment

*Reference:* [`NetworkOptions.UserAgentComment`](xref:Tableau.Migration.Config.NetworkOptions#Tableau_Migration_Config_NetworkOptions_UserAgentComment).

*Default:* [`NetworkOptions.Defaults.USER_AGENT_COMMENT`](xref:Tableau.Migration.Config.NetworkOptions.Defaults#Tableau_Migration_Config_NetworkOptions_Defaults_USER_AGENT_COMMENT).

*Python Environment Variable:* `MigrationSDK__Network__UserAgentComment`

*Reload on Edit?:* **No**. Any changes to this configuration will reflect on the next time the application starts.

*Description:* The Migration SDK appends the **UserAgentComment** property to the User-Agent header in all HTTP requests. This property is only used to assist in server-side debugging and it not typically set.


### DefaultPermissionsContentTypes.UrlSegments

*Reference:* [`DefaultPermissionsContentTypeOptions.UrlSegments`](xref:Tableau.Migration.Config.DefaultPermissionsContentTypeOptions#Tableau_Migration_Config_DefaultPermissionsContentTypeOptions_UrlSegments).
Expand Down
Loading

0 comments on commit ea65ff2

Please sign in to comment.