public ServiceResources(DeploymentV1 deployment, StatefulSetV1 statefulSet, ServiceV1 service, IngressV1Beta1 ingress, SecretV1 secret) { Deployment = deployment; StatefulSet = statefulSet; Service = service; Ingress = ingress; Secret = secret; }
/// <summary> /// Request creation of a <see cref="StatefulSetV1"/>. /// </summary> /// <param name="newStatefulSet"> /// A <see cref="StatefulSetV1"/> representing the StatefulSet to create. /// </param> /// <param name="cancellationToken"> /// An optional <see cref="CancellationToken"/> that can be used to cancel the request. /// </param> /// <returns> /// A <see cref="StatefulSetV1"/> representing the current state for the newly-created StatefulSet. /// </returns> public async Task <StatefulSetV1> Create(StatefulSetV1 newStatefulSet, CancellationToken cancellationToken = default) { if (newStatefulSet == null) { throw new ArgumentNullException(nameof(newStatefulSet)); } return(await Http .PostAsJsonAsync( Requests.Collection.WithTemplateParameters(new { Namespace = newStatefulSet?.Metadata?.Namespace ?? KubeClient.DefaultNamespace }), postBody : newStatefulSet, cancellationToken : cancellationToken ) .ReadContentAsObjectV1Async <StatefulSetV1>("create v1/StatefulSet resource")); }
private async Task <ServiceResources> DeployService(DeployCommand.Types.Service command, string kubeNamespace) { DeploymentV1 deployment = null; StatefulSetV1 statefulSet = null; var secret = await CreateSecret(); if (string.IsNullOrWhiteSpace(command.PersistentStoragePath)) { deployment = await CreateDeployment(); } else { statefulSet = await CreateStatefulSet(); } var service = await CreateService(); var ingress = await CreateServiceIngress(); return(new ServiceResources(deployment, statefulSet, service, ingress, secret)); async Task <SecretV1> CreateSecret() { if (!command.Secrets.Any()) { return(null); } var existingSecret = await kubeApiClient.SecretsV1().Get(command.Name, kubeNamespace); var secretResource = new SecretV1 { Metadata = new ObjectMetaV1 { Name = command.Name, Namespace = kubeNamespace, }, Type = "Opaque", }; if (existingSecret != null) { foreach (var existingData in existingSecret.Data) { secretResource.Data[existingData.Key] = existingData.Value; } } foreach (var secretCommand in command.Secrets.Where(s => s.Value != null)) { secretResource.Data[secretCommand.Name] = Convert.ToBase64String(Encoding.UTF8.GetBytes(secretCommand.Value)); } foreach (var existingSecretNames in secretResource.Data.Keys) { if (command.Secrets.All(secretCommand => secretCommand.Name != existingSecretNames)) { secretResource.Data.Remove(existingSecretNames); } } return(await kubeApiClient.Dynamic().Apply(secretResource, fieldManager: "clud", force: true)); } async Task <DeploymentV1> CreateDeployment() { var deployment = new DeploymentV1 { Metadata = new ObjectMetaV1 { Name = command.Name, Namespace = kubeNamespace, }, Spec = new DeploymentSpecV1 { Selector = new LabelSelectorV1 { MatchLabels = { { KubeNaming.AppLabelKey, command.Name } }, }, Replicas = command.Replicas, Template = new PodTemplateSpecV1 { Metadata = new ObjectMetaV1 { Name = command.Name, Namespace = kubeNamespace, Labels = { { KubeNaming.AppLabelKey, command.Name } } }, Spec = new PodSpecV1 { Containers = { new ContainerV1 { Name = command.Name, Image = DockerImageName(), } }, }, } } }; AddEnvironmentVariables(deployment.Spec.Template.Spec.Containers.Single().Env); return(await kubeApiClient.Dynamic().Apply(deployment, fieldManager: "clud", force: true)); } async Task <StatefulSetV1> CreateStatefulSet() { var statefulSet = new StatefulSetV1 { Metadata = new ObjectMetaV1 { Name = command.Name, Namespace = kubeNamespace, }, Spec = new StatefulSetSpecV1 { Selector = new LabelSelectorV1 { MatchLabels = { { KubeNaming.AppLabelKey, command.Name } }, }, Template = new PodTemplateSpecV1 { Metadata = new ObjectMetaV1 { Name = command.Name, Namespace = kubeNamespace, Labels = { { KubeNaming.AppLabelKey, command.Name } } }, Spec = new PodSpecV1 { Containers = { new ContainerV1 { Name = command.Name, Image = DockerImageName(), VolumeMounts = { new VolumeMountV1 { Name = command.Name, MountPath = command.PersistentStoragePath, } } }, }, }, }, VolumeClaimTemplates = { new PersistentVolumeClaimV1 { Metadata = new ObjectMetaV1 { Name = command.Name, Namespace = kubeNamespace, }, Spec = new PersistentVolumeClaimSpecV1 { AccessModes ={ "ReadWriteOnce" }, Resources = new ResourceRequirementsV1 { Requests ={ { "storage", "100Mi" } }, } } } } } }; AddEnvironmentVariables(statefulSet.Spec.Template.Spec.Containers.Single().Env); return(await kubeApiClient.Dynamic().Apply(statefulSet, fieldManager: "clud", force: true)); } string DockerImageName() { return(command.IsPublicDockerImage ? command.DockerImage : $"{KubeNaming.DockerRegistryLocation}/{command.DockerImage}"); } void AddEnvironmentVariables(List <EnvVarV1> envVarV1s) { envVarV1s.AddRange(command.EnvironmentVariables.Select(env => new EnvVarV1 { Name = env.Name, Value = env.Value })); envVarV1s.AddRange(command.Secrets.Select(secret => new EnvVarV1 { Name = secret.Name, ValueFrom = new EnvVarSourceV1 { SecretKeyRef = new SecretKeySelectorV1 { Name = command.Name, Key = secret.Name, Optional = false, } } })); } async Task <ServiceV1> CreateService() { var service = new ServiceV1 { Metadata = new ObjectMetaV1 { Name = command.Name, Namespace = kubeNamespace, }, Spec = new ServiceSpecV1 { Selector = { { KubeNaming.AppLabelKey, command.Name } }, }, }; if (command.HttpPort != null) { service.Spec.Ports.Add(new ServicePortV1 { Name = KubeNaming.HttpPortName, Protocol = "TCP", Port = command.HttpPort.Value }); } service.Spec.Ports.AddRange(command.TcpPorts.Select(port => new ServicePortV1 { Name = $"tcp-{port}", Protocol = "TCP", Port = port, })); service.Spec.Ports.AddRange(command.UdpPorts.Select(port => new ServicePortV1 { Name = $"udp-{port}", Protocol = "UDP", Port = port, })); return(await kubeApiClient.Dynamic().Apply(service, fieldManager: "clud", force: true)); } async Task <IngressV1Beta1> CreateServiceIngress() { if (command.HttpPort == null) { return(null); } var ingress = new IngressV1Beta1 { Metadata = new ObjectMetaV1 { Name = command.Name, Namespace = kubeNamespace, }, Spec = new IngressSpecV1Beta1 { Rules = { new IngressRuleV1Beta1 { Host = $"{command.Name}-{kubeNamespace}.{cludOptions.BaseHostname}", Http = new HTTPIngressRuleValueV1Beta1 { Paths = { new HTTPIngressPathV1Beta1 { Path = "/", Backend = new IngressBackendV1Beta1 { ServiceName = service.Metadata.Name, ServicePort = KubeNaming.HttpPortName, } } } } } }, }, }; return(await kubeApiClient.Dynamic().Apply(ingress, fieldManager: "clud", force: true)); } }