예제 #1
0
        public void RootCertificateConstructedFromCertificateParameterWhenProvided()
        {
            const string certificate =
                @"-----BEGIN CERTIFICATE-----
MIIC+zCCAeOgAwIBAgIJAIC+9fYZ2Xu1MA0GCSqGSIb3DQEBBQUAMBQxEjAQBgNV
BAMMCWxvY2FsaG9zdDAeFw0xOTEwMDYxMjE2MDFaFw0yOTEwMDMxMjE2MDFaMBQx
EjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBALWQJx3SZiW4plqZSpjz0PFU9QR3IcK27Du6Tr7wlBErfdEdUJ/TuC72EFWF
yR4/pCWfmiIwZnkxJGVwjaRbi0B/hza9ifbr+7uqxlVYZUN8lt5UtFpFuRvs5g69
uEutlJx/dUmvPQOoW1DzmqUAKlum8vzhcRZaSYKtWnLyGb0ec20B6Sa1nrEQtW0h
LofTJ6JvTk+MZmCTzIfeBsNz2iLDdSYDr7rlP/lWkJh+XjzFPBCDJILP1JUwPOrF
AUpwuejqm4BecjLlquPN8Lqpf7Zp1X5WCU81AQyuHXlv3FdayL8VTJGhoTRpCrvU
s5WnZgrOq3IAAk8agme+JbL6NqUCAwEAAaNQME4wHQYDVR0OBBYEFMNqhycFj+RF
LmxsR4EMu0mpnJL3MB8GA1UdIwQYMBaAFMNqhycFj+RFLmxsR4EMu0mpnJL3MAwG
A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADqFsU9l2PJsCiGtU4C3tsAz
LwHUEvOHRjXFU9bN8LApyUIGo9qsTXLyLOLv0nIrDq1gELoKgAvuD1lbnWbcTcCG
q5/f9ttB6cT513ffm4GBTenTIHSq+FFZT6A2Mwko1+3Man2vznWjl/HF5eQ6PS7U
by/z6A9Nm1Rw8Uu541odWU8/KQCSO9c/Yo+1GsDIDj5lMfLRl21Mp/lPGbGGuGu5
iMRH8QYi7YQZ2GLbaLxSY7edJlmFGYTWWV9C9jKE3s/WMaJ6Dz7NXrQM4YOE00V8
bzUuNqNBUDUhQGQDOCem29+nhKT+GPWqDt2YRDFj80UJ5wt+ljddmlVhtRS/YgY=
-----END CERTIFICATE-----";

            var client = new KubeClient(null, certificate: certificate);

            Assert.NotNull(client.RootCertificate);
        }
예제 #2
0
        /// <summary>
        ///     Ensure that a Deployment resource exists for the specified database server.
        /// </summary>
        /// <returns>
        ///     The Deployment resource, as a <see cref="DeploymentV1Beta1"/>.
        /// </returns>
        public async Task <DeploymentV1Beta1> EnsureDeploymentPresent()
        {
            RequireCurrentState();

            DeploymentV1Beta1 existingDeployment = await FindDeployment();

            if (existingDeployment != null)
            {
                Log.LogInformation("Found existing deployment {DeploymentName} for server {ServerId}.",
                                   existingDeployment.Metadata.Name,
                                   State.Id
                                   );

                return(existingDeployment);
            }

            Log.LogInformation("Creating deployment for server {ServerId}...",
                               State.Id
                               );

            DeploymentV1Beta1 createdDeployment = await KubeClient.DeploymentsV1Beta1().Create(
                KubeResources.Deployment(State,
                                         kubeNamespace: KubeOptions.KubeNamespace
                                         )
                );

            Log.LogInformation("Successfully created deployment {DeploymentName} for server {ServerId}.",
                               createdDeployment.Metadata.Name,
                               State.Id
                               );

            return(createdDeployment);
        }
예제 #3
0
        /// <summary>
        ///     Ensure that an externally-facing Service resource exists for the specified database server.
        /// </summary>
        /// <returns>
        ///     A <see cref="Task"/> representing the operation.
        /// </returns>
        public async Task EnsureExternalServicePresent()
        {
            RequireCurrentState();

            ServiceV1 existingExternalService = await FindExternalService();

            if (existingExternalService == null)
            {
                Log.LogInformation("Creating external service for server {ServerId}...",
                                   State.Id
                                   );

                ServiceV1 createdService = await KubeClient.ServicesV1().Create(
                    KubeResources.ExternalService(State,
                                                  kubeNamespace: KubeOptions.KubeNamespace
                                                  )
                    );

                Log.LogInformation("Successfully created external service {ServiceName} for server {ServerId}.",
                                   createdService.Metadata.Name,
                                   State.Id
                                   );
            }
            else
            {
                Log.LogInformation("Found existing external service {ServiceName} for server {ServerId}.",
                                   existingExternalService.Metadata.Name,
                                   State.Id
                                   );
            }
        }
예제 #4
0
        /// <summary>
        ///     Ensure that an externally-facing Service resource does not exist for the specified database server.
        /// </summary>
        public async Task EnsureExternalServiceAbsent()
        {
            RequireCurrentState();

            ServiceV1 existingExternalService = await FindExternalService();

            if (existingExternalService != null)
            {
                Log.LogInformation("Deleting external service {ServiceName} for server {ServerId}...",
                                   existingExternalService.Metadata.Name,
                                   State.Id
                                   );

                StatusV1 result = await KubeClient.ServicesV1().Delete(
                    name: existingExternalService.Metadata.Name,
                    kubeNamespace: KubeOptions.KubeNamespace
                    );

                if (result.Status != "Success" && result.Reason != "NotFound")
                {
                    Log.LogError("Failed to delete external service {ServiceName} for server {ServerId} (Message:{FailureMessage}, Reason:{FailureReason}).",
                                 existingExternalService.Metadata.Name,
                                 State.Id,
                                 result.Message,
                                 result.Reason
                                 );
                }

                Log.LogInformation("Deleted external service {ServiceName} for server {ServerId}.",
                                   existingExternalService.Metadata.Name,
                                   State.Id
                                   );
            }
        }
예제 #5
0
        /// <summary>
        ///     Ensure that a PersistentVolumeClaim for data exists for the specified database server.
        /// </summary>
        /// <returns>
        ///     The PersistentVolumeClaim resource, as a <see cref="PersistentVolumeClaimV1"/>.
        /// </returns>
        public async Task <PersistentVolumeClaimV1> EnsureDataVolumeClaimPresent()
        {
            RequireCurrentState();

            PersistentVolumeClaimV1 existingPersistentVolumeClaim = await FindDataVolumeClaim();

            if (existingPersistentVolumeClaim != null)
            {
                Log.LogInformation("Found existing data-volume claim {PersistentVolumeClaimName} for server {ServerId}.",
                                   existingPersistentVolumeClaim.Metadata.Name,
                                   State.Id
                                   );

                return(existingPersistentVolumeClaim);
            }

            Log.LogInformation("Creating data-volume claim for server {ServerId}...",
                               State.Id
                               );

            PersistentVolumeClaimV1 createdPersistentVolumeClaim = await KubeClient.PersistentVolumeClaimsV1().Create(
                KubeResources.DataVolumeClaim(State,
                                              kubeNamespace: KubeOptions.KubeNamespace
                                              )
                );

            Log.LogInformation("Successfully created data-volume claim {PersistentVolumeClaimName} for server {ServerId}.",
                               createdPersistentVolumeClaim.Metadata.Name,
                               State.Id
                               );

            return(createdPersistentVolumeClaim);
        }
        public Task InitializeGatewayListProvider()
        {
            this._kube = new KubeClient(
                this._loggerFactory, null, this._options.APIEndpoint, this._options.Group,
                this._options.APIToken, this._options.CertificateData);

            return(Task.CompletedTask);
        }
예제 #7
0
        static void Main(string[] args)
        {
            settings = JsonConfiguration.Build("./settings.json");
            kube     = new KubeClient(settings["KubernetesConfig"]);

            CheckQueue().Wait();
            Console.ReadLine();
        }
예제 #8
0
        /// <summary>
        ///     Ensure that a PersistentVolumeClaim for data does not exist for the specified database server.
        /// </summary>
        /// <returns>
        ///     <c>true</c>, if the controller is now absent; otherwise, <c>false</c>.
        /// </returns>
        public async Task <bool> EnsureDataVolumeClaimAbsent()
        {
            RequireCurrentState();

            PersistentVolumeClaimV1 dataVolumeClaim = await FindDataVolumeClaim();

            if (dataVolumeClaim == null)
            {
                return(true);
            }

            Log.LogInformation("Deleting data-volume claim {PersistentVolumeClaimName} for server {ServerId}...",
                               dataVolumeClaim.Metadata.Name,
                               State.Id
                               );

            try
            {
                await KubeClient.PersistentVolumeClaimsV1().Delete(
                    name: dataVolumeClaim.Metadata.Name,
                    kubeNamespace: KubeOptions.KubeNamespace,
                    propagationPolicy: DeletePropagationPolicy.Background
                    );

                string dataVolumeName = dataVolumeClaim.Spec.VolumeName;
                if (!String.IsNullOrWhiteSpace(dataVolumeClaim.Spec.VolumeName))
                {
                    Log.LogInformation("Deleting data volume {PersistentVolumeName} for server {ServerId}...",
                                       dataVolumeName,
                                       State.Id
                                       );

                    await KubeClient.PersistentVolumesV1().Delete(
                        name: dataVolumeName,
                        kubeNamespace: KubeOptions.KubeNamespace
                        );
                }
            }
            catch (HttpRequestException <StatusV1> deleteFailed)
            {
                Log.LogError("Failed to delete data-volume claim {PersistentVolumeClaimName} for server {ServerId} (Message:{FailureMessage}, Reason:{FailureReason}).",
                             dataVolumeClaim.Metadata.Name,
                             State.Id,
                             deleteFailed.Response.Message,
                             deleteFailed.Response.Reason
                             );

                return(false);
            }

            Log.LogInformation("Deleted data-volume claim {PersistentVolumeClaimName} for server {ServerId}.",
                               dataVolumeClaim.Metadata.Name,
                               State.Id
                               );

            return(true);
        }
예제 #9
0
        /// <summary>
        ///     Find the server's associated Secret for credentials.
        /// </summary>
        /// <returns>
        ///     The Secret, or <c>null</c> if it was not found.
        /// </returns>
        public async Task <SecretV1> FindCredentialsSecret()
        {
            RequireCurrentState();

            List <SecretV1> matchingSecrets = await KubeClient.SecretsV1().List(
                labelSelector: $"cloud.dimensiondata.daas.server-id = {State.Id}, cloud.dimensiondata.daas.secret-type = credentials",
                kubeNamespace: KubeOptions.KubeNamespace
                );

            if (matchingSecrets.Count == 0)
            {
                return(null);
            }

            return(matchingSecrets[matchingSecrets.Count - 1]);
        }
예제 #10
0
        /// <summary>
        ///     Find the server's associated ServiceMonitor (if it exists).
        /// </summary>
        /// <returns>
        ///     The ServiceMonitor, or <c>null</c> if it was not found.
        /// </returns>
        public async Task <PrometheusServiceMonitorV1> FindServiceMonitor()
        {
            RequireCurrentState();

            List <PrometheusServiceMonitorV1> matchingServices = await KubeClient.PrometheusServiceMonitorsV1().List(
                labelSelector: $"cloud.dimensiondata.daas.server-id = {State.Id},cloud.dimensiondata.daas.monitor-type = database-server",
                kubeNamespace: KubeOptions.KubeNamespace
                );

            if (matchingServices.Count == 0)
            {
                return(null);
            }

            return(matchingServices[matchingServices.Count - 1]);
        }
예제 #11
0
        /// <summary>
        ///     Find the server's associated externally-facing Service (if it exists).
        /// </summary>
        /// <returns>
        ///     The Service, or <c>null</c> if it was not found.
        /// </returns>
        public async Task <ServiceV1> FindExternalService()
        {
            RequireCurrentState();

            List <ServiceV1> matchingServices = await KubeClient.ServicesV1().List(
                labelSelector: $"cloud.dimensiondata.daas.server-id = {State.Id},cloud.dimensiondata.daas.service-type = external",
                kubeNamespace: KubeOptions.KubeNamespace
                );

            if (matchingServices.Count == 0)
            {
                return(null);
            }

            return(matchingServices[matchingServices.Count - 1]);
        }
예제 #12
0
        /// <summary>
        ///     Find the server's associated PersistentVolumeClaim for data (if it exists).
        /// </summary>
        /// <returns>
        ///     The PersistentVolumeClaim, or <c>null</c> if it was not found.
        /// </returns>
        public async Task <PersistentVolumeClaimV1> FindDataVolumeClaim()
        {
            RequireCurrentState();

            List <PersistentVolumeClaimV1> matchingPersistentVolumeClaims = await KubeClient.PersistentVolumeClaimsV1().List(
                labelSelector: $"cloud.dimensiondata.daas.server-id = {State.Id}, cloud.dimensiondata.daas.volume-type = data",
                kubeNamespace: KubeOptions.KubeNamespace
                );

            if (matchingPersistentVolumeClaims.Count == 0)
            {
                return(null);
            }

            return(matchingPersistentVolumeClaims[matchingPersistentVolumeClaims.Count - 1]);
        }
예제 #13
0
        /// <summary>
        ///     Find the server's associated Deployment (if it exists).
        /// </summary>
        /// <returns>
        ///     The Deployment, or <c>null</c> if it was not found.
        /// </returns>
        public async Task <DeploymentV1Beta1> FindDeployment()
        {
            RequireCurrentState();

            List <DeploymentV1Beta1> matchingDeployments = await KubeClient.DeploymentsV1Beta1().List(
                labelSelector: $"cloud.dimensiondata.daas.server-id = {State.Id}",
                kubeNamespace: KubeOptions.KubeNamespace
                );

            if (matchingDeployments.Count == 0)
            {
                return(null);
            }

            return(matchingDeployments[matchingDeployments.Count - 1]);
        }
예제 #14
0
        static async Task Main(string[] args)
        {
            settings = JsonConfiguration.Build("./settings.json");

            var connectionString = Environment.GetEnvironmentVariable("CONNECTION_STRING");
            var kubeConfig       = Environment.GetEnvironmentVariable("KUBE_CONIFG");
            var queueName        = Environment.GetEnvironmentVariable("QUEUE_NAME");

            containerName  = Environment.GetEnvironmentVariable("CONTAINER_NAME");
            containerImage = Environment.GetEnvironmentVariable("CONTAINER_IMAGE");
            k8Namespace    = Environment.GetEnvironmentVariable("K8S_NAMESPACE");
            k8Secret       = Environment.GetEnvironmentVariable("K8S_SECRET");

            try
            {
                containerLimit = int.Parse(Environment.GetEnvironmentVariable("MAX_CONTAINERS"));
            }
            catch {
                containerLimit = 5;
            }


            if (String.IsNullOrWhiteSpace(connectionString))
            {
                throw new ApplicationException("Connection String was not provided!!!");
            }
            if (String.IsNullOrWhiteSpace(kubeConfig))
            {
                throw new ApplicationException("KubeConfig was not provided!!!");
            }

            if (connectionString.IndexOf("AccountName") != -1) //Storage Account
            {
                queueClient = new StorageQueueClient(connectionString);
            }
            else
            {
                queueClient = new ServiceBusQueueClient(connectionString); //Service Bus
            }
            kube = new KubeClient(kubeConfig);

            rule = new IncrementRule(new TimeSpan(0, 1, 0)); // Scaling rule

            await CheckQueue(rule, queueName);
        }
예제 #15
0
        /// <summary>
        ///     Get the public TCP port number on which the database server is accessible.
        /// </summary>
        /// <param name="server">
        ///     A <see cref="DatabaseServer"/> describing the server.
        /// </param>
        /// <param name="kubeNamespace">
        ///     An optional target Kubernetes namespace.
        /// </param>
        /// <returns>
        ///     The port, or <c>null</c> if the externally-facing service for the server cannot be found.
        /// </returns>
        public async Task <int?> GetPublicPort()
        {
            RequireCurrentState();

            List <ServiceV1> matchingServices = await KubeClient.ServicesV1().List(
                labelSelector: $"cloud.dimensiondata.daas.server-id = {State.Id}, cloud.dimensiondata.daas.service-type = external",
                kubeNamespace: KubeOptions.KubeNamespace
                );

            if (matchingServices.Count == 0)
            {
                return(null);
            }

            ServiceV1 externalService = matchingServices[matchingServices.Count - 1];

            return(externalService.Spec.Ports[0].NodePort);
        }
예제 #16
0
        static async Task CreateKubeJob(KubeClient kubeClient, ConfigurationKubernetes configuration, string label, int jobCount = 1)
        {
            if (jobCount <= 0)
            {
                return;
            }

            var configMap = await kubeClient.GetConfigMapListAsync(configuration.K8Namespace, configuration.JobConfigMapName);

            if (configMap == null)
            {
                throw new ApplicationException($"Configuration Map '{configuration.JobConfigMapName}' for the nanny queue");
            }

            var job_name = Guid.NewGuid().ToString();

            Console.WriteLine($"Job {job_name} has been created!");
            var job = await kubeClient.CreateJobAsync(job_name, jobCount, 1, configuration.ContainerName, configuration.ContainerImage, configuration.K8Secret, label, configMap.Data, configuration.K8Namespace, configuration.JobCpuRequest, configuration.JobMemRequest, configuration.JobCpuLimit, configuration.JobMemLimit);
        }
예제 #17
0
        /// <summary>
        ///     Ensure that a Deployment resource does not exist for the specified database server.
        /// </summary>
        /// <returns>
        ///     <c>true</c>, if the controller is now absent; otherwise, <c>false</c>.
        /// </returns>
        public async Task <bool> EnsureDeploymentAbsent()
        {
            RequireCurrentState();

            DeploymentV1Beta1 controller = await FindDeployment();

            if (controller == null)
            {
                return(true);
            }

            Log.LogInformation("Deleting deployment {DeploymentName} for server {ServerId}...",
                               controller.Metadata.Name,
                               State.Id
                               );

            try
            {
                await KubeClient.DeploymentsV1Beta1().Delete(
                    name: controller.Metadata.Name,
                    kubeNamespace: KubeOptions.KubeNamespace,
                    propagationPolicy: DeletePropagationPolicy.Background
                    );
            }
            catch (HttpRequestException <StatusV1> deleteFailed)
            {
                Log.LogError("Failed to delete deployment {DeploymentName} for server {ServerId} (Message:{FailureMessage}, Reason:{FailureReason}).",
                             controller.Metadata.Name,
                             State.Id,
                             deleteFailed.Response.Message,
                             deleteFailed.Response.Reason
                             );

                return(false);
            }

            Log.LogInformation("Deleted deployment {DeploymentName} for server {ServerId}.",
                               controller.Metadata.Name,
                               State.Id
                               );

            return(true);
        }
예제 #18
0
        public async Task InitializeMembershipTable(bool tryInitTableVersion)
        {
            this._kube = new KubeClient(this._loggerFactory, this._options.APIEndpoint,
                                        this._options.Group, this._options.APIToken, this._options.CertificateData);

            if (this._options.CanCreateResources)
            {
                if (this._options.DropResourcesOnInit)
                {
                    await TryDeleteResources();
                }
                await TryCreateResources();
            }

            if (tryInitTableVersion)
            {
                await TryInitClusterVersion();
            }
        }
예제 #19
0
        static async Task CheckQueue(IQueueClient queueClient, KubeClient kubeClient, IScalingRule scalingRule, ConfigurationValues configuration, ConfigurationManager configurationManager)
        {
            Console.WriteLine("Nanny.Checker is Running.");

            var queueName = configuration.Queue.QueueName;

            do
            {
                if (!configurationManager.GetNotRequired("NANNY_IS_ACTIVE", defaultValue: true))
                {
                    var nextCheck = 60;
                    Console.WriteLine($"Waiting for {nextCheck} seconds, before checking queue {queueName}");
                    await Task.Delay(nextCheck * 1000);
                }

                var messageCount = await queueClient.GetMessageCountAsync(queueName);

                Console.WriteLine($"There are {messageCount} messages in the queue {queueName}");

                var currentRunningJobs = await GetCurrentRunningJobs(kubeClient, configuration.Kubernetes.K8Namespace, queueName);

                Console.WriteLine($"I have found {messageCount} jobs in Kubernetes");

                if (await kubeClient.IsResourceAvailableAsync() && currentRunningJobs < configuration.Kubernetes.ContainerLimit)
                {
                    var result = scalingRule.GetJobScalingResult(messageCount, currentRunningJobs);

                    if (result.JobCount > 0)
                    {
                        Console.WriteLine($"Creating {result.JobCount} jobs");
                        await CreateKubeJob(kubeClient, configuration.Kubernetes, queueName, result.JobCount);
                    }
                    Console.WriteLine($"Waiting for {result.NextCheck.TotalSeconds} seconds, before checking queue {queueName}");
                    await Task.Delay(result.NextCheck);
                }
                else
                {
                    Console.WriteLine("No more resources available in the cluster!");
                    await Task.Delay(5 * 60 * 1000);
                }
            } while (true);
        }
예제 #20
0
        /// <summary>
        ///     Ensure that a Secret for credentials does not exist for the specified database server.
        /// </summary>
        /// <returns>
        ///     <c>true</c>, if the controller is now absent; otherwise, <c>false</c>.
        /// </returns>
        public async Task <bool> EnsureCredentialsSecretAbsent()
        {
            RequireCurrentState();

            SecretV1 credentialsSecret = await FindCredentialsSecret();

            if (credentialsSecret == null)
            {
                return(true);
            }

            Log.LogInformation("Deleting credentials secret {SecretName} for server {ServerId}...",
                               credentialsSecret.Metadata.Name,
                               State.Id
                               );

            try
            {
                await KubeClient.SecretsV1().Delete(
                    name: credentialsSecret.Metadata.Name,
                    kubeNamespace: KubeOptions.KubeNamespace
                    );
            }
            catch (HttpRequestException <StatusV1> deleteFailed)
            {
                Log.LogError("Failed to delete credentials secret {SecretName} for server {ServerId} (Message:{FailureMessage}, Reason:{FailureReason}).",
                             credentialsSecret.Metadata.Name,
                             State.Id,
                             deleteFailed.Response.Message,
                             deleteFailed.Response.Reason
                             );

                return(false);
            }

            Log.LogInformation("Deleted credentials secret {SecretName} for server {ServerId}.",
                               credentialsSecret.Metadata.Name,
                               State.Id
                               );

            return(true);
        }
        public string Delete([FromBody] Models.RepoData RepositoryData)
        {
            MySqlConnection con = new MySqlConnection(conBuilder.GetConnectionString(true));

            string Command = $"DELETE FROM Repositories WHERE ID=@RepoID";

            MySqlCommand cmd = new MySqlCommand(Command, con);

            cmd.Parameters.AddWithValue("@RepoID", RepositoryData.Name);
            con.Open();

            cmd.ExecuteNonQuery();

            KubeClient.DeleteNamespacedDeployment(RepositoryData.Name, Settings.KubernetesNamespace);
            KubeClient.DeleteNamespacedService(RepositoryData.Name, Settings.KubernetesNamespace);
            KubeClient.DeleteNamespacedIngress(RepositoryData.Name, Settings.KubernetesNamespace);
            KubeClient.DeleteNamespacedPersistentVolumeClaim(RepositoryData.Name, Settings.KubernetesNamespace);

            return(RepositoryData.Name);
        }
예제 #22
0
        /// <summary>
        ///     Determine the connection string for the specified server.
        /// </summary>
        /// <param name="serverId">
        ///     The Id of the target server.
        /// </param>
        /// <returns>
        ///     The base UR.
        /// </returns>
        async Task <Uri> GetServerBaseAddress(string serverId)
        {
            if (String.IsNullOrWhiteSpace(serverId))
            {
                throw new ArgumentException("Argument cannot be null, empty, or entirely composed of whitespace: 'serverId'.", nameof(serverId));
            }

            Log.LogInformation("Determining connection string for server {ServerId}...",
                               serverId
                               );

            DatabaseServer targetServer = await GetServer(serverId);

            List <ServiceV1> matchingServices = await KubeClient.ServicesV1().List(
                labelSelector: $"cloud.dimensiondata.daas.server-id = {serverId},cloud.dimensiondata.daas.service-type = internal",
                kubeNamespace: KubeOptions.KubeNamespace
                );

            if (matchingServices.Count == 0)
            {
                Log.LogWarning("Cannot determine connection string for server {ServerId} (server's associated Kubernetes Service not found).",
                               serverId
                               );

                throw RespondWith(NotFound(new
                {
                    Reason     = "EndPointNotFound",
                    Id         = serverId,
                    EntityType = "DatabaseServer",
                    Message    = $"Cannot determine base address for server '{targetServer.Id}'."
                }));
            }

            ServiceV1 serverService = matchingServices[matchingServices.Count - 1];
            string    serverFQDN    = $"{serverService.Metadata.Name}.{serverService.Metadata.Namespace}.svc.cluster.local";
            int       serverPort    = serverService.Spec.Ports[0].Port;

            Log.LogInformation("Database proxy will connect to RavenDB server '{ServerFQDN}' on {ServerPort}.", serverFQDN, serverPort);

            return(new Uri($"http://{serverFQDN}:{serverPort}"));
        }
예제 #23
0
        /// <summary>
        ///     Ensure that a ServiceMonitor resource does not exist for the specified database server.
        /// </summary>
        public async Task EnsureServiceMonitorAbsent()
        {
            RequireCurrentState();

            if (State.Kind != DatabaseServerKind.SqlServer)
            {
                Log.LogInformation("Skipping monitoring configuration for server {ServerId} (not SQL Server).", State.Id);

                return;
            }

            PrometheusServiceMonitorV1 existingServiceMonitor = await FindServiceMonitor();

            if (existingServiceMonitor != null)
            {
                Log.LogInformation("Deleting service monitor {ServiceName} for server {ServerId}...",
                                   existingServiceMonitor.Metadata.Name,
                                   State.Id
                                   );

                StatusV1 result = await KubeClient.PrometheusServiceMonitorsV1().Delete(
                    name: existingServiceMonitor.Metadata.Name,
                    kubeNamespace: KubeOptions.KubeNamespace
                    );

                if (result.Status != "Success" && result.Reason != "NotFound")
                {
                    Log.LogError("Failed to delete service monitor {ServiceName} for server {ServerId} (Message:{FailureMessage}, Reason:{FailureReason}).",
                                 existingServiceMonitor.Metadata.Name,
                                 State.Id,
                                 result.Message,
                                 result.Reason
                                 );
                }

                Log.LogInformation("Deleted service monitor {ServiceName} for server {ServerId}.",
                                   existingServiceMonitor.Metadata.Name,
                                   State.Id
                                   );
            }
        }
예제 #24
0
        static async Task Main(string[] args)
        {
            var configurationManager = new ConfigurationManager(args);
            var configuration        = ConfigurationValues.GetFromConfigurationManager(configurationManager);

            IQueueClient queueClient = QueueClientFactory.GetQueueClientFromConnectionString(configuration.Queue.ConnectionString);

            KubeClient kubeClient;

            if (String.IsNullOrWhiteSpace(configuration.Kubernetes.KubeConfig))
            {
                kubeClient = new KubeClient();
            }
            else
            {
                kubeClient = new KubeClient(configuration.Kubernetes.KubeConfig);
            }

            IScalingRule scalingRule = new IncrementRule(new TimeSpan(0, 1, 0));

            await CheckQueue(queueClient, kubeClient, scalingRule, configuration, configurationManager);
        }
예제 #25
0
        /// <summary>
        ///     Ensure that a ServiceMonitor resource exists for the specified database server.
        /// </summary>
        /// <returns>
        ///     The Service resource, as a <see cref="ServiceV1"/>.
        /// </returns>
        public async Task EnsureServiceMonitorPresent()
        {
            RequireCurrentState();

            if (State.Kind != DatabaseServerKind.SqlServer)
            {
                Log.LogInformation("Skipping monitoring configuration for server {ServerId} (not SQL Server).", State.Id);

                return;
            }

            PrometheusServiceMonitorV1 existingServiceMonitor = await FindServiceMonitor();

            if (existingServiceMonitor == null)
            {
                Log.LogInformation("Creating service monitor for server {ServerId}...",
                                   State.Id
                                   );

                PrometheusServiceMonitorV1 createdService = await KubeClient.PrometheusServiceMonitorsV1().Create(
                    KubeResources.ServiceMonitor(State,
                                                 kubeNamespace: KubeOptions.KubeNamespace
                                                 )
                    );

                Log.LogInformation("Successfully created service monitor {ServiceName} for server {ServerId}.",
                                   createdService.Metadata.Name,
                                   State.Id
                                   );
            }
            else
            {
                Log.LogInformation("Found existing service monitor {ServiceName} for server {ServerId}.",
                                   existingServiceMonitor.Metadata.Name,
                                   State.Id
                                   );
            }
        }
예제 #26
0
        static async Task Main(string[] args)
        {
            var client = KubeClient.Create(KubernetesVersion.v1_15);

            var pods = await client.List <Pod>("docker");

            var pods2 = await client.ListRaw <Pod>("docker");

            var allPods = await client.List <Pod>();

            var allPods2 = await client.ListRaw <Pod>();

            var dockerPod = await client.Get <Pod>("docker", pods.Items.First().Metadata.Name);

            var foo = await client.Get <Foo>("default", "a-foo");

            await client.Patch(pods.Items.First(), (resource, patch) => {
                resource.Metadata.Annotations.Add("key", "value");
                patch.Replace(x => x.Metadata.Annotations, foo.Metadata.Annotations);
            });

            Console.ReadKey();
        }
예제 #27
0
        /// <summary>
        ///     Ensure that a Secret for data exists for the specified database server.
        /// </summary>
        /// <returns>
        ///     The Secret resource, as a <see cref="SecretV1"/>.
        /// </returns>
        public async Task <SecretV1> EnsureCredentialsSecretPresent()
        {
            RequireCurrentState();

            SecretV1 existingSecret = await FindCredentialsSecret();

            if (existingSecret != null)
            {
                Log.LogInformation("Found existing credentials secret {SecretName} for server {ServerId}.",
                                   existingSecret.Metadata.Name,
                                   State.Id
                                   );

                return(existingSecret);
            }

            Log.LogInformation("Creating credentials secret for server {ServerId}...",
                               State.Id
                               );

            Log.LogInformation("Requesting X.509 certificate...");

            CertificateCredentials serverCertificate = await RequestServerCertificate();

            SecretV1 createdSecret = await KubeClient.SecretsV1().Create(
                KubeResources.CredentialsSecret(State, serverCertificate,
                                                kubeNamespace: KubeOptions.KubeNamespace
                                                )
                );

            Log.LogInformation("Successfully created credentials secret {SecretName} for server {ServerId}.",
                               createdSecret.Metadata.Name,
                               State.Id
                               );

            return(createdSecret);
        }
예제 #28
0
 public APITest(APIFixture fixture)
 {
     this._kubeClient = fixture.Client;
 }
예제 #29
0
 static async Task <int> GetCurrentRunningJobs(KubeClient kubeClient, string _namespace, string labelSelector = "")
 {
     return(await kubeClient.GetActivePodCountFromNamespaceAsync(_namespace, labelSelector));
 }
예제 #30
0
        /// <summary>
        ///     Determine the connection string for the specified <see cref="SqlRequest"/>.
        /// </summary>
        /// <param name="request">
        ///     The <see cref="SqlRequest"/> being executed.
        /// </param>
        /// <returns>
        ///     The connection string.
        /// </returns>
        async Task <string> GetConnectionString(SqlRequest request)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            Log.LogInformation("Determining connection string for database {DatabaseId} in server {ServerId}...",
                               request.DatabaseId,
                               request.ServerId
                               );

            DatabaseServer targetServer = await DocumentSession.LoadAsync <DatabaseServer>(request.ServerId);

            if (targetServer == null)
            {
                Log.LogWarning("Cannot determine connection string for database {DatabaseId} in server {ServerId} (server not found).",
                               request.DatabaseId,
                               request.ServerId
                               );

                throw RespondWith(Ok(new SqlResult
                {
                    ResultCode = -1,
                    Errors     =
                    {
                        new SqlError
                        {
                            Kind    = SqlErrorKind.Infrastructure,
                            Message = $"Unable to determine connection settings for database {request.DatabaseId} in server {request.ServerId} (server not found)."
                        }
                    }
                }));
            }

            List <ServiceV1> matchingServices = await KubeClient.ServicesV1().List(
                labelSelector: $"cloud.dimensiondata.daas.server-id = {targetServer.Id},cloud.dimensiondata.daas.service-type = internal",
                kubeNamespace: KubeOptions.KubeNamespace
                );

            if (matchingServices.Count == 0)
            {
                Log.LogWarning("Cannot determine connection string for database {DatabaseId} in server {ServerId} (server's associated Kubernetes Service not found).",
                               request.DatabaseId,
                               request.ServerId
                               );

                throw RespondWith(Ok(new SqlResult
                {
                    ResultCode = -1,
                    Errors     =
                    {
                        new SqlError
                        {
                            Kind    = SqlErrorKind.Infrastructure,
                            Message = $"Unable to determine connection settings for database {request.DatabaseId} in server {request.ServerId} (server's associated Kubernetes Service not found)."
                        }
                    }
                }));
            }

            ServiceV1 serverService = matchingServices[matchingServices.Count - 1];

            (string serverFQDN, int?serverPort) = serverService.GetHostAndPort(portName: "sql-server");
            if (serverPort == null)
            {
                Log.LogWarning("Cannot determine connection string for database {DatabaseId} in server {ServerId} (cannot find the port named 'sql-server' on server's associated Kubernetes Service).",
                               request.DatabaseId,
                               request.ServerId
                               );

                throw RespondWith(Ok(new SqlResult
                {
                    ResultCode = -1,
                    Errors     =
                    {
                        new SqlError
                        {
                            Kind    = SqlErrorKind.Infrastructure,
                            Message = $"Unable to determine connection settings for database {request.DatabaseId} in server {request.ServerId} (cannot find the port named 'sql-server' on server's associated Kubernetes Service)."
                        }
                    }
                }));
            }

            Log.LogInformation("Database proxy will connect to SQL Server '{ServerFQDN}' on {ServerPort}.", serverFQDN, serverPort);

            var connectionStringBuilder = new SqlClient.SqlConnectionStringBuilder
            {
                DataSource = $"tcp:{serverFQDN},{serverPort}",
            };

            var serverSettings = targetServer.GetSettings <SqlServerSettings>();

            if (request.DatabaseId != MasterDatabaseId)
            {
                DatabaseInstance targetDatabase = await DocumentSession.LoadAsync <DatabaseInstance>(request.DatabaseId);

                if (targetDatabase == null)
                {
                    Log.LogWarning("Cannot determine connection string for database {DatabaseId} in server {ServerId} (database not found).",
                                   request.DatabaseId,
                                   request.ServerId
                                   );

                    throw RespondWith(Ok(new SqlResult
                    {
                        ResultCode = -1,
                        Errors     =
                        {
                            new SqlError
                            {
                                Kind    = SqlErrorKind.Infrastructure,
                                Message = $"Unable to determine connection settings for database {request.DatabaseId} in server {request.ServerId} (database not found)."
                            }
                        }
                    }));
                }

                connectionStringBuilder.InitialCatalog = targetDatabase.Name;

                if (request.ExecuteAsAdminUser)
                {
                    connectionStringBuilder.UserID   = "sa";
                    connectionStringBuilder.Password = serverSettings.AdminPassword;
                }
                else
                {
                    connectionStringBuilder.UserID   = targetDatabase.DatabaseUser;
                    connectionStringBuilder.Password = targetDatabase.DatabasePassword;
                }
            }
            else
            {
                connectionStringBuilder.InitialCatalog = "master";

                connectionStringBuilder.UserID   = "sa";
                connectionStringBuilder.Password = serverSettings.AdminPassword;
            }

            Log.LogInformation("Successfully determined connection string for database {DatabaseId} ({DatabaseName}) in server {ServerId} ({ServerSqlName}).",
                               request.DatabaseId,
                               connectionStringBuilder.InitialCatalog,
                               request.ServerId,
                               connectionStringBuilder.DataSource
                               );

            return(connectionStringBuilder.ConnectionString);
        }