Specifies the location and credentials to use when communicating with an Octopus Deploy server.
 public OctopusAuthenticationProxy(IOptions<AppSettings> settings)
 {
     if (settings == null) throw new ArgumentNullException(nameof(settings));
     
     var endpoint = new OctopusServerEndpoint(settings.Value.OctopusServerAddress);
     _repository = new OctopusRepository(endpoint);
 }
 internal OctopusClient(OctopusServerEndpoint serverEndpoint, string requestingTool)
 {
     this.serverEndpoint  = serverEndpoint;
     cookieOriginUri      = BuildCookieUri(serverEndpoint);
     octopusCustomHeaders = new OctopusCustomHeaders(requestingTool);
     Repository           = new OctopusRepository(this);
 }
        /// <summary>
        ///     Creates an instance of the client.
        /// </summary>
        /// <param name="serverEndpoint">The server endpoint.</param>
        /// <param name="octopusClientOptions"></param>
        /// <returns>The <see cref="IOctopusAsyncClient" /> instance.</returns>
        public Task <IOctopusAsyncClient> CreateAsyncClient(OctopusServerEndpoint serverEndpoint,
                                                            OctopusClientOptions octopusClientOptions = null)
        {
            var requestingTool = DetermineRequestingTool();

            return(OctopusAsyncClient.Create(serverEndpoint, octopusClientOptions, requestingTool));
        }
        /// <summary>
        ///     Creates an instance of the client.
        /// </summary>
        /// <param name="serverEndpoint">The server endpoint.</param>
        /// <returns>The <see cref="IOctopusClient" /> instance.</returns>
        /// <param name="options">The configuration options for this client instance.</param>
        public IOctopusClient CreateClient(OctopusServerEndpoint serverEndpoint, OctopusClientOptions options = default)
        {
            options ??= new OctopusClientOptions();
            var requestingTool = DetermineRequestingTool();

            return(new OctopusClient(serverEndpoint, requestingTool, options));
        }
示例#5
0
        /// <summary>
        /// Initializes a new instance of the <see cref="OctopusAsyncClient" /> class.
        /// </summary>
        /// <param name="serverEndpoint">The server endpoint.</param>
        /// <param name="options">The <see cref="OctopusClientOptions" /> used to configure the behavour of the client, may be null.</param>
        OctopusAsyncClient(OctopusServerEndpoint serverEndpoint, OctopusClientOptions options)
        {
            options    = options ?? new OctopusClientOptions();
            Repository = new OctopusAsyncRepository(this);

            this.serverEndpoint = serverEndpoint;
            var handler = new HttpClientHandler()
            {
                Credentials = serverEndpoint.Credentials ?? CredentialCache.DefaultNetworkCredentials,
            };

#if HTTP_CLIENT_SUPPORTS_SSL_OPTIONS
            handler.SslProtocols = options.SslProtocols;
            ignoreSslErrors      = options.IgnoreSslErrors;
            handler.ServerCertificateCustomValidationCallback = IgnoreServerCertificateCallback;
#endif

            if (serverEndpoint.Proxy != null)
            {
                handler.Proxy = serverEndpoint.Proxy;
            }

            client = new HttpClient(handler, true);
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            client.DefaultRequestHeaders.Add(ApiConstants.ApiKeyHttpHeaderName, serverEndpoint.ApiKey);
        }
示例#6
0
        /// <summary>
        /// ProcessRecord
        /// </summary>
        protected override void ProcessRecord()
        {
            var octopusServerEndpoint = new OctopusServerEndpoint(Server, ApiKey);
            var octopus = new OctopusRepository(octopusServerEndpoint);

            SessionState.PSVariable.Set("OctopusRepository", octopus);
        }
 public ProjectAccess(OctopusUri octopusUri,ApiKey apiKey)
 {
     _octopusUri = octopusUri;
     _apiKey = apiKey;
     _octopusServerEndpoint = new OctopusServerEndpoint(_octopusUri.ToString(),_apiKey);
     _octopusRepo = new OctopusRepository(_octopusServerEndpoint);
 }
        /// <summary>
        ///     Creates an instance of the client.
        /// </summary>
        /// <param name="serverEndpoint">The server endpoint.</param>
        /// <param name="options">The configuration options for this client instance.</param>
        /// <returns>The <see cref="IOctopusAsyncClient" /> instance.</returns>
        public Task <IOctopusAsyncClient> CreateAsyncClient(OctopusServerEndpoint serverEndpoint, OctopusClientOptions options = default)
        {
            options ??= new OctopusClientOptions();
            var requestingTool = DetermineRequestingTool();

            return(OctopusAsyncClient.Create(serverEndpoint, options, requestingTool));
        }
示例#9
0
        public void Execute(string[] commandLineArguments)
        {
            var remainingArguments = optionGroups.Parse(commandLineArguments);
            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/");

            if (string.IsNullOrWhiteSpace(apiKey))
                throw new CommandException("Please specify your API key using --apiKey=ABCDEF123456789. Learn more at: https://github.com/OctopusDeploy/Octopus-Tools");

            var credentials = ParseCredentials(username, password);

            var endpoint = new OctopusServerEndpoint(serverBaseUrl, apiKey, credentials);

            repository = repositoryFactory.CreateRepository(endpoint);

            if (enableDebugging)
            {
                repository.Client.SendingOctopusRequest += request => log.Debug(request.Method + " " + request.Uri);
            }

            ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, errors) =>
            {
                if (errors == SslPolicyErrors.None)
                {
                    return true;
                }

                var certificate2 = (X509Certificate2) certificate;
                var warning = "The following certificate errors were encountered when establishing the HTTPS connection to the server: " + errors + Environment.NewLine +
                                 "Certificate subject name: " + certificate2.SubjectName.Name + Environment.NewLine +
                                 "Certificate thumbprint:   " + ((X509Certificate2) certificate).Thumbprint;

                if (ignoreSslErrors)
                {
                    log.Warn(warning);
                    log.Warn("Because --ignoreSslErrors was set, this will be ignored.");
                    return true;
                }

                log.Error(warning);
                return false;
            };

            log.Debug("Handshaking with Octopus server: " + serverBaseUrl);
            var root = repository.Client.RootDocument;
            log.Debug("Handshake successful. Octopus version: " + root.Version + "; API version: " + root.ApiVersion);

            var user = repository.Users.GetCurrent();
            if (user != null)
            {
                log.DebugFormat("Authenticated as: {0} <{1}> {2}", user.DisplayName, user.EmailAddress, user.IsService ? "(a service account)" : "");
            }

            Execute();
        }
        public OctopusProxy(IOptions<AppSettings> settings, IHttpContextAccessor httpContextAccessor)
        {
            if (settings == null) throw new ArgumentNullException(nameof(settings));

            var apiKey = httpContextAccessor.HttpContext.User.GetOctopusApiKey();
            
            var endpoint = new OctopusServerEndpoint(settings.Value.OctopusServerAddress, apiKey);
            _repository = new OctopusRepository(endpoint);
        }
示例#11
0
        private static async Task <IOctopusAsyncClient> Create(OctopusServerEndpoint serverEndpoint, OctopusClientOptions options, bool addHandler, string requestingTool = null)
        {
            var client = new OctopusAsyncClient(serverEndpoint, options ?? new OctopusClientOptions(), addHandler, requestingTool);
            // User used to see this exception
            // System.PlatformNotSupportedException: The handler does not support custom handling of certificates with this combination of libcurl (7.29.0) and its SSL backend
            await client.Repository.LoadRootDocument().ConfigureAwait(false);

            return(client);
        }
        private OctopusConnector()
        {
            User = ConfigurationManager.AppSettings["octopus-user"];
            Pass = ConfigurationManager.AppSettings["octopus-pass"];
            Server = ConfigurationManager.AppSettings["octopus-server"];
            ApiKey = ConfigurationManager.AppSettings["octopus-key"];

            endpoint = new OctopusServerEndpoint(Server, ApiKey);
            repository = new OctopusRepository(endpoint);
        }
示例#13
0
        internal OctopusClient(OctopusServerEndpoint serverEndpoint, string requestingTool, OctopusClientOptions options = default)
        {
            this.serverEndpoint = serverEndpoint;
            options ??= new OctopusClientOptions();

            httpRouteExtractor   = new HttpRouteExtractor(options.ScanForHttpRouteTypes);
            cookieOriginUri      = BuildCookieUri(serverEndpoint);
            octopusCustomHeaders = new OctopusCustomHeaders(requestingTool);
            Repository           = new OctopusRepository(this);
        }
        private Uri BuildCookieUri(OctopusServerEndpoint octopusServerEndpoint)
        {
            // The CookieContainer is a bit funny - it sets the cookie without the port, but doesn't ignore the port when retreiving cookies
            // From what I can see it uses the Uri.Authority value - which contains the port number
            // We need to clear the port in order to successfully get cookies for the same origin
            var uriBuilder = new UriBuilder(octopusServerEndpoint.OctopusServer.Resolve("/"))
            {
                Port = 0
            };

            return(uriBuilder.Uri);
        }
        private static async Task <IOctopusAsyncClient> Create(OctopusServerEndpoint serverEndpoint, OctopusClientOptions options, bool addHandler)
        {
            var client = new OctopusAsyncClient(serverEndpoint, options ?? new OctopusClientOptions(), addHandler);

            try
            {
                client.RootDocument = await client.EstablishSession().ConfigureAwait(false);

                return(client);
            }
            catch
            {
                client.Dispose();
                throw;
            }
        }
示例#16
0
        public async Task Execute(string[] commandLineArguments)
        {
            var remainingArguments = Options.Parse(commandLineArguments);
            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/");

            if (string.IsNullOrWhiteSpace(apiKey))
                throw new CommandException("Please specify your API key using --apiKey=ABCDEF123456789. Learn more at: https://github.com/OctopusDeploy/Octopus-Tools");

            var credentials = ParseCredentials(username, password);

            var endpoint = new OctopusServerEndpoint(ServerBaseUrl, apiKey, credentials);

#if !HTTP_CLIENT_SUPPORTS_SSL_OPTIONS
            ServicePointManager.ServerCertificateValidationCallback = ServerCertificateValidationCallback;
#endif

            client = await clientFactory.CreateAsyncClient(endpoint, new OctopusClientOptions()
            {
#if HTTP_CLIENT_SUPPORTS_SSL_OPTIONS
                IgnoreSslErrors = ignoreSslErrors
#endif
            }).ConfigureAwait(false);
            Repository = repositoryFactory.CreateRepository(client);
            RepositoryCommonQueries = new OctopusRepositoryCommonQueries(Repository, Log);

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

            Log.Debug("Handshaking with Octopus server: {Url:l}", ServerBaseUrl);
            var root = Repository.Client.RootDocument;
            Log.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)
            {
                Log.Debug("Authenticated as: {Name:l} <{EmailAddress:l}> {IsService:l}", user.DisplayName, user.EmailAddress, user.IsService ? "(a service account)" : "");
            }

            ValidateParameters();
            await Execute().ConfigureAwait(false);
        }
        public OctopusDeployVersion FindCurrentlyDeployedProductionVersion(string projectName, string environmentName)
        {
            var endpoint = new OctopusServerEndpoint(_octopusDeploySettings.SevrerUrl, _octopusDeploySettings.ApiKey);
            var repository = new OctopusRepository(endpoint);

            string[] projectIdList = new string[1];
            string[] environments = new string[1];

            projectIdList[0] = repository.Projects.FindByName(projectName).Id;
            environments[0] = repository.Environments.FindByName(environmentName).Id;

            var productionDeployments = repository.Deployments.FindAll(projectIdList, environments);

            var releaseId = productionDeployments.Items.First().ReleaseId;
            var release = repository.Releases.FindOne(x => x.Id == releaseId);
            var version = new OctopusDeployVersion() {DateReleaseCreated = release.Assembled.DateTime, VersionNumber = release.Version};

            return version;
        }
        public static async Task <IOctopusAsyncClient> Create(OctopusServerEndpoint serverEndpoint, OctopusClientOptions options = null)
        {
#if HTTP_CLIENT_SUPPORTS_SSL_OPTIONS
            try
            {
                return(await Create(serverEndpoint, options, true));
            }
            catch (PlatformNotSupportedException)
            {
                if (options?.IgnoreSslErrors ?? false)
                {
                    throw new Exception("This platform does not support ignoring SSL certificate errors");
                }
                return(await Create(serverEndpoint, options, false));
            }
#else
            return(await Create(serverEndpoint, options, false));
#endif
        }
        // Use the Create method to instantiate
        protected OctopusAsyncClient(OctopusServerEndpoint serverEndpoint, OctopusClientOptions options, bool addCertificateCallback, string requestingTool, IHttpRouteExtractor httpRouteExtractor)
        {
            var clientOptions = options ?? new OctopusClientOptions();

            this.serverEndpoint     = serverEndpoint;
            this.httpRouteExtractor = httpRouteExtractor;
            cookieOriginUri         = BuildCookieUri(serverEndpoint);
            var handler = new HttpClientHandler
            {
                CookieContainer = cookieContainer,
                Credentials     = serverEndpoint.Credentials ?? CredentialCache.DefaultNetworkCredentials,
                UseProxy        = clientOptions.AllowDefaultProxy
            };

            if (clientOptions.Proxy != null)
            {
                handler.UseProxy = true;
                handler.Proxy    = new ClientProxy(clientOptions.Proxy, clientOptions.ProxyUsername, clientOptions.ProxyPassword);
            }

#if HTTP_CLIENT_SUPPORTS_SSL_OPTIONS
            handler.SslProtocols = options.SslProtocols;
            if (addCertificateCallback)
            {
                ignoreSslErrors = options.IgnoreSslErrors;
                handler.ServerCertificateCustomValidationCallback = IgnoreServerCertificateCallback;
            }
#endif

            if (serverEndpoint.Proxy != null)
            {
                handler.UseProxy = true;
                handler.Proxy    = serverEndpoint.Proxy;
            }

            client         = new HttpClient(handler, true);
            client.Timeout = clientOptions.Timeout;
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            client.DefaultRequestHeaders.Add(ApiConstants.ApiKeyHttpHeaderName, serverEndpoint.ApiKey);
            client.DefaultRequestHeaders.Add("User-Agent", new OctopusCustomHeaders(requestingTool).UserAgent);
            Repository = new OctopusAsyncRepository(this);
        }
		public VariableDictionary Get(OctopusConfigurationProviderOptions options)
		{
			var variableDictionary = new VariableDictionary();

			var endpoint = new OctopusServerEndpoint(options.ServerAddress.ToString(), options.ApiKey);
			var repository = new OctopusRepository(endpoint);

			var project = repository.Projects.FindByName(options.ProjectName);
			if (project == null)
			{
				return variableDictionary;
			}

			var scopes = new Dictionary<ScopeField, string>();
			if (!string.IsNullOrEmpty(options.EnvironmentName))
			{
				scopes[ScopeField.Environment] = options.EnvironmentName;
			}
			if (!string.IsNullOrEmpty(options.MachineName))
			{
				scopes[ScopeField.Machine] = options.MachineName;
			}

			var variableSetIds = new List<string> { project.VariableSetId };
			variableSetIds.AddRange(project.IncludedLibraryVariableSetIds.Select(id => repository.LibraryVariableSets.Get(id).VariableSetId));

			var variables = new Dictionary<string, SortedSet<VariableResource>>();
			foreach (var variableSetId in variableSetIds)
			{
				var variableSet = repository.VariableSets.Get(variableSetId);
				AddVariableSet(variables, variableSet, scopes);
			}

			foreach (var variableName in variables.Keys)
			{
				variableDictionary.Set(variableName, variables[variableName].First().Value);
			}

			return variableDictionary;
		}
        protected OctopusAsyncClient(OctopusServerEndpoint serverEndpoint, OctopusClientOptions options, bool addCertificateCallback)
        {
            options    = options ?? new OctopusClientOptions();
            Repository = new OctopusAsyncRepository(this);

            this.serverEndpoint = serverEndpoint;
            cookieOriginUri     = BuildCookieUri(serverEndpoint);
            var handler = new HttpClientHandler
            {
                CookieContainer = cookieContainer,
                Credentials     = serverEndpoint.Credentials ?? CredentialCache.DefaultNetworkCredentials,
            };

            if (options.Proxy != null)
            {
                handler.UseProxy = true;
                handler.Proxy    = new ClientProxy(options.Proxy, options.ProxyUsername, options.ProxyPassword);
            }

#if HTTP_CLIENT_SUPPORTS_SSL_OPTIONS
            handler.SslProtocols = options.SslProtocols;
            if (addCertificateCallback)
            {
                ignoreSslErrors = options.IgnoreSslErrors;
                handler.ServerCertificateCustomValidationCallback = IgnoreServerCertificateCallback;
            }
#endif

            if (serverEndpoint.Proxy != null)
            {
                handler.Proxy = serverEndpoint.Proxy;
            }

            client         = new HttpClient(handler, true);
            client.Timeout = options.Timeout;
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            client.DefaultRequestHeaders.Add(ApiConstants.ApiKeyHttpHeaderName, serverEndpoint.ApiKey);
            client.DefaultRequestHeaders.Add("User-Agent", $"{ApiConstants.OctopusUserAgentProductName}/{GetType().GetSemanticVersion().ToNormalizedString()}");
        }
示例#22
0
        public OctoRepository(ServerInstanceElement instance)
        {
            ApiUri = instance.ApiUri.TrimEnd('/');

            var endpoint = new OctopusServerEndpoint(ApiUri, instance.ApiKey);
            var client = new OctopusClient(endpoint);
            _repository = new OctopusRepository(client);

            SystemInfoResource systemInfo;

            try
            {
                ServerStatusResource serverStatus = _repository.ServerStatus.GetServerStatus();
                systemInfo = _repository.ServerStatus.GetSystemInfo(serverStatus);
            }
            catch (OctopusException ex)
            {
                throw;
            }

            Version = new SemanticVersion(systemInfo.Version);

            using (var databaseModel = new DatabaseModel())
            {
                OctopusServer octopusServer = databaseModel.OctopusServers.SingleOrDefault(octo => octo.ApiUri == ApiUri);

                if (octopusServer == null)
                {
                    octopusServer = new OctopusServer();
                    octopusServer.ApiUri = ApiUri;
                    octopusServer.DisplayName = ApiUri;
                    databaseModel.OctopusServers.Add(octopusServer);
                    databaseModel.SaveChanges();
                }

                OctopusServerId = octopusServer.Id;
            }
        }
示例#23
0
 /// <summary>
 /// Creates an instance of the client.
 /// </summary>
 /// <param name="serverEndpoint">The server endpoint.</param>
 /// <returns>The <see cref="IOctopusClient" /> instance.</returns>
 // [Obsolete("Use CreateAsyncClient(OctopusServerEndpoint) instead")]
 public IOctopusClient CreateClient(OctopusServerEndpoint serverEndpoint)
 {
     return(new OctopusClient(serverEndpoint));
 }
示例#24
0
 public OctopusRepository(OctopusServerEndpoint endpoint) : this(new OctopusClient(endpoint))
 {
 }
示例#25
0
 /// <summary>
 /// Initializes a new instance of the <see cref="OctopusClient" /> class.
 /// </summary>
 /// <param name="serverEndpoint">The server endpoint.</param>
 public OctopusClient(OctopusServerEndpoint serverEndpoint)
 {
     this.serverEndpoint = serverEndpoint;
     cookieOriginUri     = BuildCookieUri(serverEndpoint);
 }
 /// <summary>
 /// Creates an instance of the client.
 /// </summary>
 /// <param name="serverEndpoint">The server endpoint.</param>
 /// <param name="octopusClientOptions"></param>
 /// <returns>The <see cref="IOctopusAsyncClient" /> instance.</returns>
 public Task<IOctopusAsyncClient> CreateAsyncClient(OctopusServerEndpoint serverEndpoint, OctopusClientOptions octopusClientOptions = null)
 {
     return OctopusAsyncClient.Create(serverEndpoint, octopusClientOptions);
 }
示例#27
0
 /// <summary>
 /// Initializes a new instance of the <see cref="OctopusClient" /> class.
 /// </summary>
 /// <param name="serverEndpoint">The server endpoint.</param>
 public OctopusClient(OctopusServerEndpoint serverEndpoint) : this(serverEndpoint, null)
 {
 }
 /// <summary>
 /// Creates an instance of the client.
 /// </summary>
 /// <param name="serverEndpoint">The server endpoint.</param>
 /// <returns>The <see cref="IOctopusClient" /> instance.</returns>
 public IOctopusClient CreateClient(OctopusServerEndpoint serverEndpoint)
 {
     return new OctopusClient(serverEndpoint);
 }
示例#29
0
 public OctopusRepository(OctopusServerEndpoint endpoint) : this(new OctopusClient(endpoint))
 {
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="OctopusClient" /> class.
 /// </summary>
 /// <param name="serverEndpoint">The server endpoint.</param>
 public OctopusClient(OctopusServerEndpoint serverEndpoint)
 {
     this.serverEndpoint = serverEndpoint;
     cookieOriginUri     = BuildCookieUri(serverEndpoint);
     clientVersion       = GetType().GetSemanticVersion();
 }
 public static OctopusRepository GetOctopusRepository()
 {
     var endPoint = new OctopusServerEndpoint(OctopusUri, ApiKey);
     return new OctopusRepository(endPoint);
 }
示例#32
0
 /// <summary>
 /// Initializes a new instance of the <see cref="OctopusClient" /> class.
 /// </summary>
 /// <param name="serverEndpoint">The server endpoint.</param>
 public OctopusClient(OctopusServerEndpoint serverEndpoint)
 {
     this.serverEndpoint = serverEndpoint;
 }
示例#33
0
 /// <summary>
 /// Creates an instance of the client.
 /// </summary>
 /// <param name="serverEndpoint">The server endpoint.</param>
 /// <param name="octopusClientOptions"></param>
 /// <returns>The <see cref="IOctopusAsyncClient" /> instance.</returns>
 public Task <IOctopusAsyncClient> CreateAsyncClient(OctopusServerEndpoint serverEndpoint, OctopusClientOptions octopusClientOptions = null)
 {
     return(OctopusAsyncClient.Create(serverEndpoint, octopusClientOptions));
 }
        /// <summary>
        ///     Creates an instance of the client.
        /// </summary>
        /// <param name="serverEndpoint">The server endpoint.</param>
        /// <returns>The <see cref="IOctopusClient" /> instance.</returns>
        public IOctopusClient CreateClient(OctopusServerEndpoint serverEndpoint)
        {
            var requestingTool = DetermineRequestingTool();

            return(new OctopusClient(serverEndpoint, requestingTool));
        }
 /// <summary>
 /// Creates an instance of the client.
 /// </summary>
 /// <param name="serverEndpoint">The server endpoint.</param>
 /// <returns>The <see cref="IOctopusClient" /> instance.</returns>
 public IOctopusClient CreateClient(OctopusServerEndpoint serverEndpoint)
 {
     return(new OctopusClient(serverEndpoint, requestingTool));
 }
示例#36
0
 public OctopusRepository(OctopusServerEndpoint endpoint, RepositoryScope repositoryScope) : this(new OctopusClient(endpoint), repositoryScope)
 {
 }
 public IOctopusRepository CreateRepository(OctopusServerEndpoint endpoint)
 {
     return new OctopusRepository(endpoint);
 }
示例#38
0
 /// <summary>
 /// Initializes a new instance of the <see cref="OctopusClient" /> class.
 /// </summary>
 /// <param name="serverEndpoint">The server endpoint.</param>
 /// <param name="options">The configuration options for this client instance.</param>
 public OctopusClient(OctopusServerEndpoint serverEndpoint, OctopusClientOptions options = default) : this(serverEndpoint, null, options)
 {
 }