/// <summary> /// Provision the site based on the provisioning manifest in a file /// </summary> /// <param name="statusLogs">Store status logs here</param> /// <param name="pathSecrets">Where the log in secrets are</param> /// <param name="pathProvisioningManifest">Where the provisioning steps are</param> /// <param name="outputPath">Where output files go</param> private void ProvisionFromFileManifest(TaskStatusLogs statusLogs, string pathSecrets, string pathProvisioningManifest, string outputPath) { //Load the config from the files var secretsConfig = new ProvisionConfigSiteAccess(pathSecrets); //Load the user provisioning instructions var provisionUsersInfo = new ProvisionUserInstructions( pathProvisioningManifest); var provisionSite = new ProvisionSite(secretsConfig, provisionUsersInfo, this, statusLogs); provisionSite.Execute(); //--------------------------------------------------------------------- //Generate an output file //--------------------------------------------------------------------- FileIOHelper.CreatePathIfNeeded(outputPath); var outputFilePath = Path.Combine(outputPath, "ProvisionSiteOutput.csv"); provisionSite.CSVResultsReport.GenerateCSVFile(outputFilePath); statusLogs.AddStatusHeader("Done!"); ((IShowLogs)this).NewLogResultsToShow(statusLogs); }
/// <summary> /// Called to perform Uploads of the data sources /// </summary> /// <param name="onlineLogin"></param> /// <param name="localBasePath"></param> /// <param name="credentialManager">Database credentials that will be associaed with uploaded content</param> private void Execute_UploadDatasources( TableauServerSignIn onlineLogin, string localBasePath, CredentialManager credentialManager) { StatusLog.AddStatusHeader("Upload datasources"); if (string.IsNullOrWhiteSpace(localBasePath)) { _statusLog.AddError("Abort uploads. Local path is not specified"); return; } string pathDataSources = Path.Combine(localBasePath, "datasources"); if (!Directory.Exists(pathDataSources)) { _statusLog.AddStatus("Skipping datasources upload. Local datasources path does not exist: \"" + pathDataSources + "\""); return; } //Upload all the files var uploadProjectBehavior = new UploadBehaviorProjects( _taskOptions.IsOptionSet(TaskMasterOptions.Option_UploadCreateNeededProjects), true); var dsUploader = new UploadDatasources( _onlineUrls, onlineLogin, credentialManager, pathDataSources, uploadProjectBehavior, _manualActions, this.UploadChunksSizeBytes, this.UploadChunksDelaySeconds); try { dsUploader.ExecuteRequest(); } catch (Exception exUploader) { StatusLog.AddError("Aborted upload datasources. Unexpected error + " + exUploader.Message); } }
/// <summary> /// Called to run us in commandn line mode /// </summary> /// <param name="commandLine"></param> internal void RunStartupCommandLine_Inner(TaskStatusLogs statusLogs) { statusLogs.AddStatusHeader("Processing command line"); string pathProvisionPlan = AppSettings.CommandLine_PathProvisionPlan; string pathSecrets = AppSettings.CommandLine_PathSecrets; string pathOutput = AppSettings.CommandLine_PathOutput; //If an output directory was not specified, then output into an "out" subdirectory in the directory where the provision plan is if (string.IsNullOrWhiteSpace(pathOutput)) { pathOutput = Path.Combine( Path.GetDirectoryName(pathProvisionPlan), "out"); } //==================================================================================== //Based on the command specified, run the specified task //==================================================================================== switch (AppSettings.CommandLine_Command) { case CommandLineParser.Command_ProvisionFromAzure: //Update the paths in the UI so the user can see & re-run them if they want txtPathToSecrets.Text = pathSecrets; txtPathToAzureAdProvisioningConfig.Text = pathProvisionPlan; //Run the work... ProvisionFromAzureAd(statusLogs, pathSecrets, pathProvisionPlan, pathOutput); break; case CommandLineParser.Command_ProvisionFromFileManifest: //Update the paths in the UI so the user can see & re-run them if they want txtPathToSecrets.Text = pathSecrets; txtPathToFileProvisioningConfig.Text = pathProvisionPlan; //Run the work... ProvisionFromFileManifest(statusLogs, pathSecrets, pathProvisionPlan, pathOutput); break; default: statusLogs.AddError("1101-432: Unknown command: " + AppSettings.CommandLine_Command); break; } }
/// <summary> /// Generate a maniefest file based on the current Online site /// </summary> /// <param name="statusLogs"></param> /// <param name="pathSecrets"></param> /// <param name="pathOutputFile"></param> /// <param name="ignoreAllUsersGroup">(recommend TRUE) If false, the manifest file will contain the "all users" group</param> private void GenerateManifestFromOnlineSite( TaskStatusLogs statusLogs, string pathSecrets, string pathOutputFile, bool ignoreAllUsersGroup) { var pathOutputs = Path.GetDirectoryName(pathOutputFile); ProvisionConfigSiteAccess secretsConfig; //=========================================================================================== //Get the sign in information //=========================================================================================== try { //Load the config from the files secretsConfig = new ProvisionConfigSiteAccess(pathSecrets); } catch (Exception exSignInConfig) { statusLogs.AddError("Error loading sign in config file"); throw new Exception("1012-327: Error parsing sign in config, " + exSignInConfig.Message); } //=========================================================================================== //Create a place for out output files //=========================================================================================== FileIOHelper.CreatePathIfNeeded(pathOutputs); var provisionSettings = ProvisionConfigExternalDirectorySync.FromDefaults(); //=========================================================================================== //Download all the data we need from the Tableau Online site //=========================================================================================== statusLogs.AddStatusHeader("Retrieving information from Tableau"); UpdateStatusText(statusLogs); var tableauDownload = new TableauProvisionDownload( secretsConfig, this, statusLogs, ignoreAllUsersGroup); try { tableauDownload.Execute(); } catch (Exception exTableauDownload) { statusLogs.AddError("Error retrieving data from Tableau"); throw new Exception("813-0148: Error in Tableau Download, " + exTableauDownload.Message); } //=========================================================================================== //Write the provisioning manifest out to a file //=========================================================================================== statusLogs.AddStatusHeader("Writing out manifest file for Tableau provisioning"); UpdateStatusText(statusLogs); var outputProvisioningRoles = tableauDownload.ProvisioningManifestResults; try { outputProvisioningRoles.GenerateProvisioningManifestFile(pathOutputFile, provisionSettings); } catch (Exception exWriteProvisioningManifest) { statusLogs.AddError("Error creating provisioning manifest"); throw new Exception("1012-252: Error writing provisioning manifest, " + exWriteProvisioningManifest.Message); } }
/// <summary> /// Run the provisioning pulling from AzureAD /// </summary> /// <param name="pathSecrets"></param> /// <param name="pathProvisionPlan"></param> private void ProvisionFromAzureAd( TaskStatusLogs statusLogs, string pathSecrets, string pathProvisionPlan, bool deployToTableauTarget, string pathOutputs) { //=========================================================================================== //Create a place for out output files //=========================================================================================== FileIOHelper.CreatePathIfNeeded(pathOutputs); AzureAdConfig configSignInAzure; ProvisionConfigExternalDirectorySync configGroupsMapping; //=========================================================================================== //Get the sign in information //=========================================================================================== try { //Load the config from the files configSignInAzure = new AzureAdConfig(pathSecrets); } catch (Exception exSignInConfig) { statusLogs.AddError("Error loading sign in config file. Error: " + exSignInConfig.Message); throw new Exception("813-1212: Error parsing sign in config, " + exSignInConfig.Message); } //=========================================================================================== //Get the Groups/Roles mapping information //=========================================================================================== try { configGroupsMapping = new ProvisionConfigExternalDirectorySync(pathProvisionPlan); } catch (Exception exGroupsMapping) { statusLogs.AddError("Error loading sync groups provisioning file. Error: " + exGroupsMapping.Message); throw new Exception("813-1214: Error parsing sync groups, " + exGroupsMapping.Message); } //=========================================================================================== //Download all the data we need from Azure //=========================================================================================== statusLogs.AddStatusHeader("Retrieving information from Azure AD"); UpdateStatusText(statusLogs); var azureDownload = new AzureDownload(configSignInAzure, configGroupsMapping, this, statusLogs, null); try { azureDownload.Execute(); //Sanity test IwsDiagnostics.Assert(azureDownload.IsExecuteComplete.Value, "813-834: Internal error. Async work still running"); } catch (Exception exAzureDownload) { statusLogs.AddError("Error retrieving data from Azure AD. Error: " + exAzureDownload.Message); throw new Exception("813-0148: Error in Azure Download, " + exAzureDownload.Message); } //=========================================================================================== //Write the provisioning manifest out to an intermediary file //=========================================================================================== statusLogs.AddStatusHeader("Writing out manifest file for Tableau provisioning"); UpdateStatusText(statusLogs); var outputProvisioningRoles = azureDownload.ProvisioningManifestResults; string provisioningManifest = Path.Combine(pathOutputs, "ProvisioningManifest.xml"); try { outputProvisioningRoles.GenerateProvisioningManifestFile(provisioningManifest, configGroupsMapping); } catch (Exception exWriteProvisioningManifest) { statusLogs.AddError("Error creating provisioning manifest. Error: " + exWriteProvisioningManifest.Message); throw new Exception("813-739: Error writing provisioning manifest, " + exWriteProvisioningManifest.Message); } //================================================================================================= //See if this is a test run, or whether we want to actually deploy the provisioning //================================================================================================= if (deployToTableauTarget) { //=========================================================================================== //Provision the Tableau site using the manifest file we just created //=========================================================================================== statusLogs.AddStatusHeader("Provision Tableau site using generated manifest file"); UpdateStatusText(statusLogs); try { ProvisionFromFileManifest(statusLogs, pathSecrets, provisioningManifest, pathOutputs); } catch (Exception exProvisionSite) { statusLogs.AddError("Error provisioning Tableau Online site. Error: " + exProvisionSite.Message); throw new Exception("814-353: Error provisioning Tableau Online site, " + exProvisionSite.Message); } } else { statusLogs.AddStatusHeader("Skipping Tableau site provisioning step (generate manifest only)"); } }
/// <summary> /// Called to attempt to execute a custom command (to be run after the user logs in) /// </summary> /// <param name="onlineLogin"></param> /// <param name="customCommand"></param> private void AttemptExecutionOfCustomHttpGet(TableauServerSignIn onlineLogin, string customCommand) { _statusLog.AddStatusHeader("GET request: " + customCommand); var customGetRequest = new SendPostLogInCommand(_onlineUrls, onlineLogin, customCommand); try { var customResult = customGetRequest.ExecuteRequest(); _statusLog.AddStatus("GET result: " + customResult); } catch (Exception exCustomCommand) { _statusLog.AddError("Error during custom GET, " + exCustomCommand.ToString()); } }