Example #1
0
 private void Awake()
 {
     if (instance == null)
     {
         instance = this;
     }
 }
        public async Task ListAsync(Settings settings)
        {
            if (!await PopulateDeploymentTierSettingsAsync(settings, requireBucketName: false, requireCoreServices: false, requireVersionCheck: false))
            {
                return;
            }

            // gather module details
            var tierManager   = new TierManager(settings);
            var moduleDetails = await tierManager.GetModuleDetailsAsync();

            // sort and format output
            if (moduleDetails.Any())
            {
                Console.WriteLine();
                Console.WriteLine($"Found {moduleDetails.Count():N0} modules for deployment tier {Settings.InfoColor}{tierManager.TierName}{Settings.ResetColor}");
                Console.WriteLine();
                tierManager.ShowModuleDetails(
                    moduleDetails.OrderBy(module => module.DeploymentDate),
                    (ColumnTitle: "NAME", GetColumnValue: module => module.ModuleDeploymentName),
                    (ColumnTitle: "MODULE", GetColumnValue: module => module.ModuleReference),
                    (ColumnTitle: "STATUS", GetColumnValue: module => module.StackStatus),
                    (ColumnTitle: "DATE", GetColumnValue: module => module.DeploymentDate.ToString("yyyy-MM-dd HH:mm:ss"))
                    );
            }
            else
            {
                Console.WriteLine();
                Console.WriteLine($"Found no modules for deployment tier {Settings.InfoColor}{tierManager.TierName}{Settings.ResetColor}");
            }
        }
Example #3
0
 private void ShowModuleDetails(TierManager tierManager, IEnumerable <TierModuleDetails> moduleDetails)
 {
     tierManager.ShowModuleDetails(
         moduleDetails.OrderBy(module => module.ModuleDeploymentName),
         (ColumnTitle: "NAME", GetColumnValue: module => module.ModuleDeploymentName),
         (ColumnTitle: "MODULE", GetColumnValue: module => module.ModuleReference),
         (ColumnTitle: "STATUS", GetColumnValue: module => module.StackStatus),
         (ColumnTitle: "CORE-SERVICES", GetColumnValue: module => module.CoreServices?.ToUpperInvariant() ?? "N/A")
         );
 }
Example #4
0
        void OnInitialize(EventArgs e)
        {
            #region Config

            string path = Path.Combine(TShock.SavePath, "CTRSystem", "CTRS-Config.json");
            Config    = Configuration.ConfigFile.Read(path);
            Formatter = new TextFormatter(this, Config);

            #endregion

            #region Commands

            Commands = new CommandManager(this);

            Action <Command> Add = c =>
            {
                TShockAPI.Commands.ChatCommands.RemoveAll(c2 => c2.Names.Exists(s => c.Names.Contains(s)));
                TShockAPI.Commands.ChatCommands.Add(c);
            };

            Add(new Command(Permissions.Admin, Commands.CAdmin, "cadmin")
            {
                HelpText = "Perform administrative actions across the Contributions Track & Reward System."
            });

            Add(new Command(Permissions.Commands, Commands.Contributions,
                            new List <string>(Config.AdditionalCommandAliases)
            {
                "ctrs"
            }.ToArray())
            {
                HelpText = "Manages contributor settings. You must have contributed at least once before using this command."
            });

            Add(new Command(Permissions.Auth, Commands.Authenticate, "auth", "authenticate")
            {
                DoLog    = false,
                HelpText = "Connects your Xenforo account to your TShock account. Enter your forum credentials OR generate an auth code first by visiting your user control panel."
            });

            #endregion

            _tierUpdateTimer          = new Timer(Config.TierRefreshMinutes * 60 * 1000);
            _tierUpdateTimer.Elapsed += UpdateTiers;
            _tierUpdateTimer.Start();

            Contributors     = new ContributorManager(this);
            CredentialHelper = new LoginManager(this);
            Rests            = new RestManager(this);
            Tiers            = new TierManager(this);
            XenforoUsers     = new XenforoManager(this);
        }
        public MenuItemMasterViewModel()
        {
            TableDropDown tdd = new TableDropDown();

            LocationList       = tdd.SetLocationDropDown();
            StoreList          = tdd.SetStoreDropDown();
            MenuItemMasterList = new List <MenuItem>();
            MenuRecipeList     = new List <MenuRecipe>();
            TierList           = TierManager.SetTierList();
            TradingAreaList    = tdd.SetTradingAreaList();
            CategoryList       = tdd.SetCategoryList();
            MIMFGCList         = tdd.SetPMGList("PMGFGC");
            MIMHPTList         = tdd.SetPMGList("PMGHPT");
            MIMWGRList         = tdd.SetPMGList("PMGWGR");
            GroupList          = tdd.SetGroupList();
            MasterList         = new List <MenuItemMasterViewModel>();
        }
        public async Task List(Settings settings)
        {
            if (!await PopulateDeploymentTierSettingsAsync(settings, requireBucketName: false, requireCoreServices: false, requireVersionCheck: false))
            {
                return;
            }

            // gather module details
            var tierManager   = new TierManager(settings);
            var moduleDetails = await tierManager.GetModuleDetailsAsync();

            // sort and format output
            tierManager.ShowModuleDetails(
                moduleDetails.OrderBy(module => module.DeploymentDate),
                (ColumnTitle: "NAME", GetColumnValue: module => module.ModuleDeploymentName),
                (ColumnTitle: "MODULE", GetColumnValue: module => module.ModuleReference),
                (ColumnTitle: "STATUS", GetColumnValue: module => module.StackStatus),
                (ColumnTitle: "DATE", GetColumnValue: module => module.DeploymentDate.ToString("yyyy-MM-dd HH:mm:ss"))
                );
        }
Example #7
0
        //--- Methods ---
        public void Register(CommandLineApplication app)
        {
            app.Command("tier", cmd => {
                cmd.HelpOption();
                cmd.Description = "Tier utility commands";

                // function sub-command
                cmd.Command("coreservices", subCmd => {
                    subCmd.HelpOption();
                    subCmd.Description = "Enable/disable LambdaSharp.Core services for all modules in tier";

                    // command options
                    var enabledOption        = subCmd.Option("--enabled", "(optional) Enable LambdaSharp.Core services for all modules", CommandOptionType.NoValue);
                    var disabledOption       = subCmd.Option("--disabled", "(optional) Disable LambdaSharp.Core services for all modules", CommandOptionType.NoValue);
                    var initSettingsCallback = CreateSettingsInitializer(subCmd);
                    AddStandardCommandOptions(subCmd);
                    subCmd.OnExecute(async() => {
                        ExecuteCommandActions(subCmd);
                        var settings = await initSettingsCallback();
                        if (settings == null)
                        {
                            return;
                        }
                        if (enabledOption.HasValue() && disabledOption.HasValue())
                        {
                            LogError("--enabled and --disabled options are mutually exclusive");
                            return;
                        }
                        bool?enabled = null;
                        if (enabledOption.HasValue())
                        {
                            enabled = true;
                        }
                        else if (disabledOption.HasValue())
                        {
                            enabled = false;
                        }
                        await UpdateCoreServicesAsync(settings, enabled, showModules: true);
                    });
                });

                // check tier version
                cmd.Command("version", subCmd => {
                    subCmd.HelpOption();
                    subCmd.Description       = "Check Tier Version";
                    var minVersionOption     = subCmd.Option("--min-version", "(optional) Minimum expected version", CommandOptionType.SingleValue);
                    var initSettingsCallback = CreateSettingsInitializer(subCmd);
                    AddStandardCommandOptions(subCmd);

                    // run command
                    subCmd.OnExecute(async() => {
                        ExecuteCommandActions(subCmd);
                        var settings = await initSettingsCallback();
                        if (settings == null)
                        {
                            return(-1);
                        }

                        // fetch tier information
                        if (!await PopulateDeploymentTierSettingsAsync(settings, optional: true))
                        {
                            if (!Program.Quiet)
                            {
                                Console.WriteLine();
                                Console.WriteLine($"No deployment tier found {Settings.OutputColor}[ExitCode: 2]{Settings.ResetColor}");
                            }
                            return(2);
                        }

                        // validate options
                        if (minVersionOption.Value() == null)
                        {
                            Console.WriteLine();
                            Console.WriteLine($"Deployment tier version: {Settings.InfoColor}{settings.TierVersion}{Settings.ResetColor}");
                            return(0);
                        }
                        else
                        {
                            if (!VersionInfo.TryParse(minVersionOption.Value(), out var minVersion))
                            {
                                LogError("invalid value for --min-version option");
                                return(-1);
                            }

                            // compare version numbers
                            var exitCode = settings.TierVersion.IsGreaterOrEqualThanVersion(minVersion) ? 0 : 1;
                            if (!Program.Quiet)
                            {
                                Console.WriteLine();
                                Console.WriteLine($"Deployment tier version: {Settings.InfoColor}{settings.TierVersion} {Settings.OutputColor}[ExitCode: {exitCode}]{Settings.ResetColor}");
                            }
                            return(exitCode);
                        }
                    });
                });

                // check tier version
                cmd.Command("list", subCmd => {
                    subCmd.HelpOption();
                    subCmd.Description = "List all available deployment tiers";

                    // command options
                    var initSettingsCallback = CreateSettingsInitializer(subCmd);
                    AddStandardCommandOptions(subCmd);
                    subCmd.OnExecute(async() => {
                        ExecuteCommandActions(subCmd);
                        var settings = await initSettingsCallback();
                        if (settings == null)
                        {
                            return;
                        }

                        // gather module details
                        var tierManager = new TierManager(settings);
                        var tierDetails = await tierManager.GetDeploymentTierDetailsAsync();
                        if (tierDetails.Any())
                        {
                            Console.WriteLine();
                            Console.WriteLine($"Found {tierDetails.Count():N0} deployment tiers");
                            Console.WriteLine();
                            tierManager.ShowModuleDetails(
                                tierDetails.OrderBy(module => module.DeploymentTierName),
                                (ColumnTitle: "TIER", GetColumnValue: module => module.DeploymentTierName),
                                (ColumnTitle: "VERSION", GetColumnValue: module => ModuleInfo.TryParse(module.ModuleReference, out var moduleInfo)
                                    ? moduleInfo.Version.ToString()
                                    : module.ModuleReference),
                                (ColumnTitle: "STATUS", GetColumnValue: module => module.StackStatus),
                                (ColumnTitle: "CORE-SERVICES", GetColumnValue: module => module.CoreServices?.ToUpperInvariant() ?? "N/A")
                                );
                        }
Example #8
0
        public async Task UpdateCoreServicesAsync(Settings settings, bool?enabled, bool showModules)
        {
            if (!await PopulateDeploymentTierSettingsAsync(settings, requireBucketName: false, requireCoreServices: false, requireVersionCheck: false))
            {
                return;
            }

            // gather module details
            var tierManager   = new TierManager(settings);
            var moduleDetails = (await tierManager.GetModuleDetailsAsync())
                                .OrderBy(details => details.ModuleDeploymentName)
                                .ToList();

            if (showModules)
            {
                ShowModuleDetails(tierManager, moduleDetails);
            }

            // check if tier has any stacks
            if (!moduleDetails.Any())
            {
                return;
            }

            // validate that all modules in tier can enable/disable core services
            if (enabled.HasValue)
            {
                foreach (var details in moduleDetails)
                {
                    if (details.CoreServices == null)
                    {
                        LogError($"${details.ModuleDeploymentName} does not support enabling/disabling LambdaSharp.Core services");
                    }
                    else if (!enabled.Value && details.HasDefaultSecretKeyParameter)
                    {
                        LogError($"${details.ModuleDeploymentName} cannot disable LambdaSharp.Core services, because it depends on DefaultSecretKey");
                    }
                }
            }
            if (!enabled.HasValue || HasErrors)
            {
                return;
            }

            // update core services for each affected root module
            var coreServicesParameter = enabled.Value ? "Enabled" : "Disabled";
            var modulesToUpdate       = moduleDetails
                                        .Where(module => module.CoreServices != coreServicesParameter)
                                        .Where(module => module.IsRoot)
                                        .ToList();

            if (!modulesToUpdate.Any())
            {
                return;
            }
            Console.WriteLine($"=> {(enabled.Value ? "Enabling" : "Disabling")} modules in deployment tier '{settings.TierName}'");
            var parameters = new Dictionary <string, string> {
                ["LambdaSharpCoreServices"] = coreServicesParameter
            };

            foreach (var module in modulesToUpdate)
            {
                await UpdateStackParameters(settings, module, parameters);
            }
            Console.WriteLine();

            // show updated state
            if (showModules)
            {
                ShowModuleDetails(tierManager, await tierManager.GetModuleDetailsAsync());
            }
        }
Example #9
0
        public async Task NukeAsync(Settings settings, bool dryRun, bool confirmed)
        {
            if (!await PopulateDeploymentTierSettingsAsync(settings, requireBucketName: false, requireCoreServices: false, requireVersionCheck: false))
            {
                return;
            }

            // gather module details
            Console.WriteLine($"=> Inspecting deployment tier {Settings.InfoColor}{settings.TierName}{Settings.ResetColor}");
            var tierManager = new TierManager(settings);

            // enumerate all non-nested (root) stack that in a completed update state
            var moduleDetails = (await tierManager.GetModuleDetailsAsync(includeCoreModule: true))
                                .Where(module => module.StackStatus.EndsWith("_COMPLETE") && (module.StackStatus != "DELETE_COMPLETE"))
                                .ToList();

            if (!moduleDetails.Any())
            {
                Console.WriteLine($"=> Found no modules to delete");
                return;
            }
            var count = moduleDetails.Count(module => module.IsRoot);

            if (count == 1)
            {
                Console.WriteLine($"=> Found 1 CloudFormation stack to delete");
            }
            else
            {
                Console.WriteLine($"=> Found {count:N0} CloudFormation stacks to delete");
            }

            // confirm action with user if not already confirmed and this is not a dry run
            if (!confirmed && !dryRun)
            {
                // list what is about to be deleted
                Console.WriteLine();
                foreach (var module in moduleDetails
                         .Where(module => module.IsRoot)
                         .OrderBy(module => module.ModuleDeploymentName)
                         )
                {
                    Console.WriteLine($"  {Settings.InfoColor}{module.ModuleDeploymentName}{Settings.ResetColor}");
                }

                // confirm deployment tier name
                Console.WriteLine();
                if (settings.PromptString("Confirm the deployment tier name to delete") != settings.TierName)
                {
                    LogError("deployment tier name does not match");
                    return;
                }

                // confirm action one more time
                if (!settings.PromptYesNo($"Proceed with deleting deployment tier '{settings.TierName}'", defaultAnswer: false))
                {
                    Console.WriteLine("=> Canceling deletion of deployment tier");
                    return;
                }
                Console.WriteLine();
            }

            // discover all dependencies
            var dependencies = new Dictionary <string, HashSet <string> >();

            foreach (var module in moduleDetails)
            {
                var dependents = new HashSet <string>();
                dependencies.Add(module.StackName, dependents);

                // enumerate each exported value
                foreach (var output in module.Stack.Outputs.Where(output => output.ExportName != null))
                {
                    // discover which stacks are importing it
                    try {
                        var imports = await settings.CfnClient.ListImportsAsync(new ListImportsRequest {
                            ExportName = output.ExportName
                        });

                        foreach (var import in imports.Imports)
                        {
                            dependents.Add(import);
                        }
                    } catch (AmazonCloudFormationException e) when(e.Message == $"Export '{output.ExportName}' is not imported by any stack.")
                    {
                        // nothing to do
                    }
                }
            }

            // iteratively delete the stacks
            var bucketsToDelete = new List <string>();

            for (var i = 0; moduleDetails.Any() && (i < MAX_ITERATIONS); ++i)
            {
                foreach (var module in moduleDetails.Where(module => module.IsRoot).ToList())
                {
                    var stackName = module.StackName;

                    // skip stacks that still have dependents
                    if (dependencies[stackName].Any())
                    {
                        Settings.LogInfoVerbose($"... skipping due to active dependencies: {stackName}");
                        continue;
                    }
                    if ((module.DeploymentBucketArn != null) && (moduleDetails.Count > 1))
                    {
                        // don't delete the LambdaSharp.Core stack until all other modules have been deleted
                        continue;
                    }

                    // show progress
                    Console.WriteLine($"=> Deleting {Settings.InfoColor}{stackName}{Settings.ResetColor}");
                    if (!dryRun)
                    {
                        // check if this is the LambdaSharp.Core stack
                        if (module.DeploymentBucketArn != null)
                        {
                            var resources = await settings.CfnClient.GetStackResourcesAsync(module.StackName);

                            // check if this stack created its own deployment bucket
                            var deploymentBucketName = resources.FirstOrDefault(resource => resource.LogicalResourceId == "DeploymentBucketResource")?.PhysicalResourceId;
                            if (deploymentBucketName != null)
                            {
                                await DeleteBucketContentsAsync(settings, "deployment bucket", deploymentBucketName);

                                bucketsToDelete.Add(deploymentBucketName);
                            }

                            // check if this stack created its own logging bucket
                            var loggingBucketName = resources.FirstOrDefault(resource => resource.LogicalResourceId == "LoggingBucketResource")?.PhysicalResourceId;
                            if (loggingBucketName != null)
                            {
                                await DeleteBucketContentsAsync(settings, "logging bucket", loggingBucketName);

                                bucketsToDelete.Add(loggingBucketName);
                            }
                        }

                        // delete stack
                        var mostRecentStackEventId = await settings.CfnClient.GetMostRecentStackEventIdAsync(stackName);

                        var oldNameMappings = await new ModelManifestLoader(settings, "source").GetNameMappingsFromCloudFormationStackAsync(stackName);
                        await settings.CfnClient.DeleteStackAsync(new DeleteStackRequest {
                            StackName = stackName
                        });

                        var outcome = await settings.CfnClient.TrackStackUpdateAsync(
                            stackName,
                            module.Stack.StackId,
                            mostRecentStackEventId,
                            nameMappings : null,
                            oldNameMappings,
                            LogError
                            );

                        // confirm that stack is deleted
                        var stackEventsResponse = await settings.CfnClient.DescribeStackEventsAsync(new DescribeStackEventsRequest {
                            StackName = module.Stack.StackId
                        });

                        var success = (stackEventsResponse.StackEvents.First().ResourceStatus == ResourceStatus.DELETE_COMPLETE);
                        if (!success)
                        {
                            Console.WriteLine("=> Stack delete FAILED");
                            LogError($"unable to delete {stackName}");
                            return;
                        }
                        Console.WriteLine("=> Stack delete finished");
                    }

                    // remove this stack and its children from the list of stacks to delete
                    RecursiveRemoveFromModuleDetails(module);
                }
            }

            // delete any left over buckets, such as the logging bucket which has 'Retain' as deletion policy
            if (bucketsToDelete.Any())
            {
                Console.WriteLine();
                foreach (var bucketName in bucketsToDelete)
                {
                    if (await settings.S3Client.DoesS3BucketExistAsync(bucketName))
                    {
                        try {
                            Console.WriteLine($"=> Deleting S3 Bucket {Settings.InfoColor}{bucketName}{Settings.ResetColor}");
                            await settings.S3Client.DeleteBucketAsync(bucketName);
                        } catch {
                            LogWarn($"unable to delete S3 bucket: {bucketName}");
                        }
                    }
                }
            }

            // local functions
            void RecursiveRemoveFromModuleDetails(TierModuleDetails moduleToRemove)
            {
                // remove this stack as a dependent from all dependencies
                foreach (var dependency in dependencies)
                {
                    dependency.Value.Remove(moduleToRemove.StackName);
                }

                // find all child modules of the module to remove
                foreach (var childModule in moduleDetails.Where(module => module.Stack.RootId == moduleToRemove.Stack.StackId).ToList())
                {
                    RecursiveRemoveFromModuleDetails(childModule);
                }

                // remove module from list
                moduleDetails.RemoveAll(moduleDetail => moduleDetail.StackName == moduleToRemove.StackName);
            }
        }