예제 #1
0
        public virtual void GetHelp(TextWriter writer, string[] args)
        {
            var typeInfo = this.GetType().GetTypeInfo();

            var    executable       = AssemblyExtensions.GetExecutableName();
            var    commandAttribute = typeInfo.GetCustomAttribute <CommandAttribute>();
            string commandName;
            var    description = string.Empty;

            if (commandAttribute == null)
            {
                commandName = args.FirstOrDefault();
            }
            else
            {
                commandName = commandAttribute.Name;
                description = commandAttribute.Description;
            }

            commandOutputProvider.PrintMessages = HelpOutputFormat == OutputFormat.Default;
            if (HelpOutputFormat == OutputFormat.Json)
            {
                PrintJsonHelpOutput(writer, commandName, description);
            }
            else
            {
                PrintDefaultHelpOutput(writer, executable, commandName, description);
            }
        }
예제 #2
0
        protected override async Task Execute()
        {
            commandOutputProvider.Warning($"The {AssemblyExtensions.GetExecutableName()} import/export commands have been deprecated. See https://g.octopushq.com/DataMigration for alternative options.");

            if (string.IsNullOrWhiteSpace(Type))
            {
                throw new CommandException("Please specify the type of object to import using the parameter: --type=XYZ");
            }
            if (string.IsNullOrWhiteSpace(FilePath))
            {
                throw new CommandException("Please specify the full path and name of the export file to import using the parameter: --filePath=XYZ");
            }

            commandOutputProvider.Debug("Finding importer '{Type:l}'", Type);
            var importer = importerLocator.Find(Type, Repository, FileSystem, commandOutputProvider);

            if (importer == null)
            {
                throw new CommandException("Error: Unrecognized importer '" + Type + "'");
            }

            commandOutputProvider.Debug("Validating the import");
            var validationResult = await importer.Validate(string.Format("FilePath={0}", FilePath), string.Format("Project={0}", Project)).ConfigureAwait(false);

            if (validationResult && !DryRun)
            {
                commandOutputProvider.Debug("Beginning the import");
                await importer.Import(string.Format("FilePath={0}", FilePath), string.Format("Project={0}", Project)).ConfigureAwait(false);
            }
        }
예제 #3
0
        public override Task Execute(string[] commandLineArguments)
        {
            return(Task.Run(() =>
            {
                Options.Parse(commandLineArguments);

                commandOutputProvider.PrintMessages = OutputFormat == OutputFormat.Default;

                executable = AssemblyExtensions.GetExecutableName();

                var commandName = commandLineArguments.FirstOrDefault();

                if (string.IsNullOrEmpty(commandName))
                {
                    PrintGeneralHelp();
                }
                else
                {
                    var command = commands.Find(commandName);

                    if (command == null)
                    {
                        if (!commandName.StartsWith("--"))
                        {
                            // wasn't a parameter!
                            Console.ForegroundColor = ConsoleColor.Red;
                            Console.WriteLine("Command '{0}' is not supported", commandName);
                        }

                        Console.ResetColor();
                        PrintGeneralHelp();
                    }
                    else
                    {
                        PrintCommandHelp(command, commandLineArguments);
                    }
                }
            }));
        }
예제 #4
0
        protected override Task Execute()
        {
            commandOutputProvider.Warning($"The {AssemblyExtensions.GetExecutableName()} import/export commands have been deprecated. See https://g.octopushq.com/DataMigration for alternative options.");

            if (string.IsNullOrWhiteSpace(Type))
            {
                throw new CommandException("Please specify the type to export using the parameter: --type=XYZ");
            }
            if (string.IsNullOrWhiteSpace(FilePath))
            {
                throw new CommandException("Please specify the full path and name of the export file using the parameter: --filePath=XYZ");
            }

            commandOutputProvider.Debug("Finding exporter '{Type:l}'", Type);
            var exporter = exporterLocator.Find(Type, Repository, FileSystem, commandOutputProvider);

            if (exporter == null)
            {
                throw new CommandException("Error: Unrecognized exporter '" + Type + "'");
            }

            commandOutputProvider.Debug("Beginning the export");
            return(exporter.Export(string.Format("FilePath={0}", FilePath), string.Format("Project={0}", Project), string.Format("Name={0}", Name), string.Format("ReleaseVersion={0}", ReleaseVersion)));
        }
예제 #5
0
        static int PrintError(Exception ex)
        {
            switch (ex)
            {
            case AggregateException agg:
            {
                var errors = new HashSet <Exception>(agg.InnerExceptions);
                if (agg.InnerException != null)
                {
                    errors.Add(ex.InnerException);
                }

                var lastExit = 0;
                foreach (var inner in errors)
                {
                    lastExit = PrintError(inner);
                }

                return(lastExit);
            }

            case OctopusSecurityException securityException:
            {
                if (!string.IsNullOrWhiteSpace(securityException.HelpText))
                {
                    Log.Error(securityException.HelpText);
                }

                Log.Error(securityException.Message);
                return(-5);
            }

            case CommandException cmd:
            {
                Log.Error(ex.Message);
                if (CommandOutputProviderExtensionMethods.IsKnownEnvironment())
                {
                    Log.Error($"This error is most likely occurring while executing {AssemblyExtensions.GetExecutableName()} as part of an automated build process. The following doc is recommended to get some tips on how to troubleshoot this: https://g.octopushq.com/OctoexeTroubleshooting");
                }
                return(-1);
            }

            case ReflectionTypeLoadException reflex:
            {
                Log.Error(ex, string.Empty);

                foreach (var loaderException in reflex.LoaderExceptions)
                {
                    Log.Error(loaderException, string.Empty);
                }

                return(-43);
            }

            case UnsupportedApiVersionException unsupported:
            {
                Log.Error(unsupported.Message);
                return(-1);
            }

            case OctopusException octo:
            {
                Log.Information("{HttpErrorMessage:l}", octo.Message);
                Log.Error("Error from Octopus Server (HTTP {StatusCode} {StatusDescription})",
                          octo.HttpStatusCode,
                          (HttpStatusCode)octo.HttpStatusCode);
                return(-7);
            }
            }

            Log.Error(ex, string.Empty);
            return(-3);
        }
예제 #6
0
        public override async Task Execute(string[] commandLineArguments)
        {
            var remainingArguments = Options.Parse(commandLineArguments);

            if (printHelp)
            {
                GetHelp(Console.Out, commandLineArguments);

                return;
            }

            if (remainingArguments.Count > 0)
            {
                throw new CommandException("Unrecognized command arguments: " + string.Join(", ", remainingArguments));
            }

            if (string.IsNullOrWhiteSpace(ServerBaseUrl))
            {
                throw new CommandException("Please specify the Octopus Server URL using --server=http://your-server/. " +
                                           $"The Octopus Server URL can also be set in the {ServerUrlEnvVar} environment variable.");
            }

            if (!string.IsNullOrWhiteSpace(ApiKey) && !string.IsNullOrWhiteSpace(Username))
            {
                throw new CommandException("Please provide an API Key OR a username and password, not both. " +
                                           "These values may have been passed in as command line arguments, or may have been set in the " +
                                           $"{ApiKeyEnvVar} and {UsernameEnvVar} environment variables.");
            }

            if (string.IsNullOrWhiteSpace(ApiKey) && string.IsNullOrWhiteSpace(Username))
            {
                throw new CommandException("Please specify your API key using --apiKey=ABCDEF123456789 OR a username and password. " +
                                           $"The API key can also be set in the {ApiKeyEnvVar} environment variable, " +
                                           $"while the username and password can be set in the {UsernameEnvVar} and {PasswordEnvVar} " +
                                           "environment variables respectively. Learn more at: https://github.com/OctopusDeploy/Octopus-Tools");
            }

            var endpoint = string.IsNullOrWhiteSpace(ApiKey)
                ? new OctopusServerEndpoint(ServerBaseUrl)
                : new OctopusServerEndpoint(ServerBaseUrl, ApiKey);

#if NETFRAMEWORK
            /*
             * There may be a delay between the completion of a large file upload and when Octopus responds
             * to finish the HTTP connection. This delay can be several minutes. During this time, no traffic is
             * sent, and some networking infrastructure will close the connection. For example, Azure VMs will
             * close idle connections after 4 minutes, and AWS VMs will close them after 350 seconds. The
             * TCP keepalive option will ensure that the connection is not idle at the end of the file upload.
             *
             * This is the bug that explains why this doesn't work with .NET Core:
             * https://github.com/dotnet/corefx/issues/26013
             */
            if (keepAlive > 0)
            {
                ServicePointManager.FindServicePoint(new Uri(ServerBaseUrl)).SetTcpKeepAlive(true, keepAlive, keepAlive);
            }
#endif

#if HTTP_CLIENT_SUPPORTS_SSL_OPTIONS
            clientOptions.IgnoreSslErrors = ignoreSslErrors;
#else
            ServicePointManager.ServerCertificateValidationCallback = ServerCertificateValidationCallback;
#endif

            commandOutputProvider.PrintMessages = OutputFormat == OutputFormat.Default || enableDebugging;
            CliSerilogLogProvider.PrintMessages = commandOutputProvider.PrintMessages;
            commandOutputProvider.PrintHeader();

            var client = await clientFactory.CreateAsyncClient(endpoint, clientOptions).ConfigureAwait(false);

            if (!string.IsNullOrWhiteSpace(Username))
            {
                await client.Repository.Users.SignIn(Username, Password).ConfigureAwait(false);
            }

            var serverHasSpaces = await client.ForSystem().HasLink("Spaces").ConfigureAwait(false);

            if (!string.IsNullOrEmpty(spaceNameOrId))
            {
                if (!serverHasSpaces)
                {
                    throw new CommandException($"The server {endpoint.OctopusServer} has no spaces. Try invoking {AssemblyExtensions.GetExecutableName()} without specifying the space name as an argument");
                }

                var space = await client.ForSystem().Spaces.FindByNameOrIdOrFail(spaceNameOrId).ConfigureAwait(false);

                Repository = repositoryFactory.CreateRepository(client, RepositoryScope.ForSpace(space));
                commandOutputProvider.Debug("Space name specified, process is now running in the context of space: {space:l}", space.Name);
            }
            else
            {
                Repository = repositoryFactory.CreateRepository(client);

                if (!serverHasSpaces)
                {
                    commandOutputProvider.Debug("Process will run in backwards compatible mode for older versions of Octopus Server");
                }
                else
                {
                    var defaultSpace = await client.ForSystem()
                                       .Spaces.FindOne(space => space.IsDefault)
                                       .ConfigureAwait(false);

                    if (defaultSpace == null)
                    {
                        throw new CommandException("Octopus Server does not have a default space enabled, hence you need to specify the space name as an argument");
                    }

                    commandOutputProvider.Debug("Space name unspecified, process will run in the default space context");
                }
            }

            RepositoryCommonQueries = new OctopusRepositoryCommonQueries(Repository, commandOutputProvider);

            if (enableDebugging)
            {
                Repository.Client.SendingOctopusRequest += request => commandOutputProvider.Debug("{Method:l} {Uri:l}", request.Method, request.Uri);
            }

            commandOutputProvider.Debug("Handshaking with Octopus Server: {Url:l}", ServerBaseUrl);

            var root = await Repository.LoadRootDocument().ConfigureAwait(false);

            commandOutputProvider.Debug("Handshake successful. Octopus version: {Version:l}; API version: {ApiVersion:l}", root.Version, root.ApiVersion);

            var user = await Repository.Users.GetCurrent().ConfigureAwait(false);

            if (user != null)
            {
                if (string.IsNullOrEmpty(user.EmailAddress))
                {
                    commandOutputProvider.Debug("Authenticated as: {Name:l} {IsService:l}", user.DisplayName, user.IsService ? "(a service account)" : "");
                }
                else
                {
                    commandOutputProvider.Debug("Authenticated as: {Name:l} <{EmailAddress:l}> {IsService:l}", user.DisplayName, user.EmailAddress, user.IsService ? "(a service account)" : "");
                }
            }

            await ValidateParameters().ConfigureAwait(false);
            await Execute().ConfigureAwait(false);
        }