Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release 4.3.0 #35

Merged
merged 1 commit into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading