public async Task WatcherIntegrationTest() { var kubernetesConfig = KubernetesClientConfiguration.BuildConfigFromConfigFile(kubeconfigPath: @"C:\Users\frede\Source\Repos\cloud\minikube.config"); var kubernetes = new Kubernetes(kubernetesConfig); var job = await kubernetes.CreateNamespacedJobAsync( new V1Job() { ApiVersion = "batch/v1", Kind = V1Job.KubeKind, Metadata = new V1ObjectMeta() { Name = nameof(WatcherIntegrationTest).ToLowerInvariant() }, Spec = new V1JobSpec() { Template = new V1PodTemplateSpec() { Spec = new V1PodSpec() { Containers = new List <V1Container>() { new V1Container() { Image = "ubuntu/xenial", Name = "runner", Command = new List <string>() { "/bin/bash", "-c", "--" }, Args = new List <string>() { "trap : TERM INT; sleep infinity & wait" } } }, RestartPolicy = "Never" }, } } }, "default"); Collection <Tuple <WatchEventType, V1Job> > events = new Collection <Tuple <WatchEventType, V1Job> >(); AsyncManualResetEvent started = new AsyncManualResetEvent(); AsyncManualResetEvent connectionClosed = new AsyncManualResetEvent(); var watcher = await kubernetes.WatchNamespacedJobAsync( job.Metadata.Name, job.Metadata.NamespaceProperty, resourceVersion : job.Metadata.ResourceVersion, timeoutSeconds : 30, onEvent : (type, source) => { Debug.WriteLine($"Watcher 1: {type}, {source}"); events.Add(new Tuple <WatchEventType, V1Job>(type, source)); job = source; started.Set(); }, onClosed : connectionClosed.Set).ConfigureAwait(false); await started.WaitAsync(); await Task.WhenAny(connectionClosed.WaitAsync(), Task.Delay(TimeSpan.FromMinutes(3))); Assert.True(connectionClosed.IsSet); await kubernetes.DeleteNamespacedJobAsync( job.Metadata.Name, job.Metadata.NamespaceProperty, new V1DeleteOptions()); }
public async Task <Job> SubmitJob(Job job) { var resources = new V1ResourceRequirements { Requests = new Dictionary <string, ResourceQuantity>() { { "cpu", new ResourceQuantity("1") }, { "memory", new ResourceQuantity($"1Gi") } } }; var podSpec = new V1PodSpec { Containers = new[] { new V1Container { Name = job.Id, Image = _config["Pi:Docker:Image"], Command = new [] { "/app/Pi.Runtime.NetFx", "-dp", job.DecimalPlaces.ToString() }, Resources = resources } }, RestartPolicy = "Never" }; //for running in AKS with ACI integration: if (_config.GetValue <bool>("Pi:Processors:Kubernetes:UseAci")) { AddAciConfiguration(podSpec); } var jobSpec = new V1JobSpec() { Template = new V1PodTemplateSpec(spec: podSpec) }; var jobMetadata = new V1ObjectMeta(name: job.Id) { Labels = new Dictionary <string, string>() { { "com.pi", "1" } } }; var k8sJob = new V1Job(metadata: jobMetadata, spec: jobSpec); if (_logger.IsEnabled(LogLevel.Debug)) { _logger.LogDebug("*** Generated YAML: ***"); var yaml = Yaml.SaveToString(k8sJob); _logger.LogDebug(yaml); _logger.LogDebug("---"); } await _kubernetes.CreateNamespacedJobAsync(k8sJob, _namespace); job.ProcessingId = k8sJob.Metadata.Name; return(job); }
async Task StartJobFor(IPerformerLog log, Context context, Read.Configuration.Build build) { var @namespace = "dolittle"; var metadata = new V1ObjectMeta { Name = Guid.NewGuid().ToString() //, //Labels = { { "type", "build" } } }; log.Information($"---"); log.Information($"Type : {build.Type}"); log.Information($"BasePath : {build.BasePath}"); log.Information($"Package : {build.Package}"); log.Information($"Publish : {build.Publish}"); log.Information($"Folder with project to publish : {build.FolderWithProjectToPublish}"); log.Information($"---"); var job = new V1Job { Metadata = metadata, Spec = new V1JobSpec { Completions = 1, Template = new V1PodTemplateSpec { Metadata = metadata, Spec = new V1PodSpec { Containers = new [] { new V1Container { Name = "build", Image = $"dolittlebuild/{build.Type}", ImagePullPolicy = "Always", Env = new [] { new V1EnvVar("REPOSITORY", context.Project.Repository.ToString()), new V1EnvVar("COMMIT", context.SourceControl.Commit), new V1EnvVar("PULL_REQUEST", context.IsPullRequest.ToString()), new V1EnvVar("VERSION", context.Version), new V1EnvVar("BASE_PATH", build.BasePath), new V1EnvVar("PACKAGE", build.Package.ToString()), new V1EnvVar("PUBLISH", build.Publish.ToString()), new V1EnvVar("FOLDER_WITH_PROJECT_TO_PUBLISH", build.FolderWithProjectToPublish), new V1EnvVar("CALLBACK", $"http://continuousimprovement/buildJobDone?jobName={metadata.Name}") }, VolumeMounts = new[] { new V1VolumeMount { Name = "azure", MountPath = "/repository", SubPath = context.Volumes.SourcePath }, new V1VolumeMount { Name = "azure", MountPath = "/packages", SubPath = context.Volumes.PackagePath }, new V1VolumeMount { Name = "azure", MountPath = "/output", SubPath = context.Volumes.OutputPath }, new V1VolumeMount { Name = "azure", MountPath = "/publish", SubPath = context.Volumes.PublishPath }, new V1VolumeMount { Name = "azure", MountPath = "/testresults", SubPath = context.Volumes.TestResultsPath } } } }, Volumes = new[] { new V1Volume { Name = "azure", AzureFile = new V1AzureFileVolumeSource { SecretName = "azure-storage-secret", ShareName = "continuousimprovement", ReadOnlyProperty = false } } }, RestartPolicy = "Never", } } } }; await _kubernetes.CreateNamespacedJobAsync(job, @namespace); }
private async Task <bool> CreateJobAsync(WebPingerArchive archive) { // check a pinger exists to archive: var services = await _kubernetes.ListNamespacedServiceAsync( Program.NamespaceName, labelSelector : $"app=web-ping,target={archive.Spec.Target}"); if (!services.Items.Any()) { Console.WriteLine($"** No WebPinger Service exists for target: {archive.Spec.Target}, in namespace: {Program.NamespaceName}"); return(false); } var pingerServiceName = services.Items.First().Metadata.Name; var name = $"wpa-{archive.Metadata.Name}-{archive.Metadata.CreationTimestamp:yyMMdd-HHmm}"; var jobs = await _kubernetes.ListNamespacedJobAsync( Program.NamespaceName, fieldSelector : $"metadata.name={name}"); if (!jobs.Items.Any()) { var job = new V1Job { Metadata = new V1ObjectMeta { Name = name, Labels = new Dictionary <string, string>() { { "kiamol", "ch20" }, } }, Spec = new V1JobSpec { Completions = 1, Template = new V1PodTemplateSpec { Metadata = new V1ObjectMeta { Labels = new Dictionary <string, string>() { { "app", "web-ping-archive" }, { "target", archive.Spec.Target } } }, Spec = new V1PodSpec { AutomountServiceAccountToken = false, RestartPolicy = "Never", Containers = new List <V1Container> { new V1Container { Name = "archiver", Image = "kiamol/ch20-web-ping-archiver", Env = new List <V1EnvVar> { new V1EnvVar { Name = "WEB_PING_URL", Value = $"http://{pingerServiceName}:8080/archive" } } } } } } } }; await _kubernetes.CreateNamespacedJobAsync(job, Program.NamespaceName); Console.WriteLine($"** Created Job: {name}, in namespace: {Program.NamespaceName}"); return(true); } else { Console.WriteLine($"** Job exists: {name}, in namespace: {Program.NamespaceName}"); return(false); } }