public async Task PurgeModulesAsync() { // Delete all services for current edge deployment V1ServiceList services = await this.client.ListNamespacedServiceAsync(this.deviceNamespace, labelSelector : this.deploymentSelector); var serviceTasks = services.Items .Select(service => this.client.DeleteNamespacedServiceAsync(service.Metadata.Name, this.deviceNamespace, new V1DeleteOptions())); await Task.WhenAll(serviceTasks); // Delete all deployments for current edge deployment V1DeploymentList deployments = await this.client.ListNamespacedDeploymentAsync(this.deviceNamespace, labelSelector : this.deploymentSelector); var deploymentTasks = deployments.Items .Select( deployment => this.client.DeleteNamespacedDeploymentAsync( deployment.Metadata.Name, this.deviceNamespace, new V1DeleteOptions(propagationPolicy: KubernetesConstants.DefaultDeletePropagationPolicy), propagationPolicy: KubernetesConstants.DefaultDeletePropagationPolicy)); await Task.WhenAll(deploymentTasks); V1PersistentVolumeClaimList pvcs = await this.client.ListNamespacedPersistentVolumeClaimAsync(this.deviceNamespace, labelSelector : this.deploymentSelector); var pvcTasks = pvcs.Items .Select(pvc => this.client.DeleteNamespacedPersistentVolumeClaimAsync(pvc.Metadata.Name, this.deviceNamespace, new V1DeleteOptions())); await Task.WhenAll(pvcTasks); // Delete the service account for all deployments V1ServiceAccountList serviceAccounts = await this.client.ListNamespacedServiceAccountAsync(this.deviceNamespace, labelSelector : this.deploymentSelector); var serviceAccountTasks = serviceAccounts.Items .Select(service => this.client.DeleteNamespacedServiceAsync(service.Metadata.Name, this.deviceNamespace, new V1DeleteOptions())); await Task.WhenAll(serviceAccountTasks); }
public async Task PurgeModulesAsync() { // Delete all services for current edge deployment V1ServiceList services = await this.client.ListNamespacedServiceAsync(this.deviceNamespace, labelSelector : this.deploymentSelector); var serviceTasks = services.Items .Select(service => this.client.DeleteNamespacedServiceAsync(service.Metadata.Name, this.deviceNamespace, new V1DeleteOptions())); await Task.WhenAll(serviceTasks); // Delete all deployments for current edge deployment V1DeploymentList deployments = await this.client.ListNamespacedDeploymentAsync(this.deviceNamespace, labelSelector : this.deploymentSelector); var deploymentTasks = deployments.Items .Select( deployment => this.client.DeleteNamespacedDeployment1Async( deployment.Metadata.Name, this.deviceNamespace, new V1DeleteOptions(propagationPolicy: "Foreground"), propagationPolicy: "Foreground")); await Task.WhenAll(deploymentTasks); // Delete the service account for all deployments V1ServiceAccountList serviceAccounts = await this.client.ListNamespacedServiceAccountAsync(this.deviceNamespace, labelSelector : this.deploymentSelector); var serviceAccountTasks = serviceAccounts.Items .Select(service => this.client.DeleteNamespacedServiceAsync(service.Metadata.Name, this.deviceNamespace, new V1DeleteOptions())); await Task.WhenAll(serviceAccountTasks); }
public async Task <ModuleSet> DeployModulesAsync(IReadOnlyList <KubernetesModule> modules, ModuleSet currentModules) { var desiredModules = ModuleSet.Create(modules.ToArray()); var moduleIdentities = await this.moduleIdentityLifecycleManager.GetModuleIdentitiesAsync(desiredModules, currentModules); var labels = modules .ToDictionary( module => module.Name, module => new Dictionary <string, string> { [KubernetesConstants.K8sEdgeModuleLabel] = moduleIdentities[module.Name].DeploymentName(), [KubernetesConstants.K8sEdgeDeviceLabel] = KubeUtils.SanitizeLabelValue(this.resourceName.DeviceId), [KubernetesConstants.K8sEdgeHubNameLabel] = KubeUtils.SanitizeLabelValue(this.resourceName.Hostname) }); var deviceOnlyLabels = new Dictionary <string, string> { [KubernetesConstants.K8sEdgeDeviceLabel] = KubeUtils.SanitizeLabelValue(this.resourceName.DeviceId), [KubernetesConstants.K8sEdgeHubNameLabel] = KubeUtils.SanitizeLabelValue(this.resourceName.Hostname) }; var desiredServices = modules .Select(module => this.serviceMapper.CreateService(moduleIdentities[module.Name], module, labels[module.Name])) .FilterMap() .ToList(); V1ServiceList currentServices = await this.client.ListNamespacedServiceAsync(this.deviceNamespace, labelSelector : this.deploymentSelector); await this.ManageServices(currentServices, desiredServices); var desiredDeployments = modules .Select(module => this.deploymentMapper.CreateDeployment(moduleIdentities[module.Name], module, labels[module.Name])) .ToList(); V1DeploymentList currentDeployments = await this.client.ListNamespacedDeploymentAsync(this.deviceNamespace, labelSelector : this.deploymentSelector); await this.ManageDeployments(currentDeployments, desiredDeployments); var desiredPvcs = modules .Select(module => this.pvcMapper.CreatePersistentVolumeClaims(module, deviceOnlyLabels)) .FilterMap() .SelectMany(x => x) .Distinct(KubernetesPvcByValueEqualityComparer); // Modules may use PVCs created by the user, we get all PVCs and then work on ours. V1PersistentVolumeClaimList currentPvcList = await this.client.ListNamespacedPersistentVolumeClaimAsync(this.deviceNamespace); await this.ManagePvcs(currentPvcList, desiredPvcs); var desiredServiceAccounts = modules .Select(module => this.serviceAccountMapper.CreateServiceAccount(moduleIdentities[module.Name], labels[module.Name])) .ToList(); V1ServiceAccountList currentServiceAccounts = await this.client.ListNamespacedServiceAccountAsync(this.deviceNamespace, labelSelector : this.deploymentSelector); await this.ManageServiceAccounts(currentServiceAccounts, desiredServiceAccounts); return(desiredModules); }
public async Task <ModuleSet> DeployModulesAsync(IList <KubernetesModule> modules, ModuleSet currentModules) { var desiredModules = ModuleSet.Create(modules.ToArray()); var moduleIdentities = await this.moduleIdentityLifecycleManager.GetModuleIdentitiesAsync(desiredModules, currentModules); var labels = modules .ToDictionary( module => module.Name, module => new Dictionary <string, string> { [KubernetesConstants.K8sEdgeModuleLabel] = moduleIdentities[module.Name].DeploymentName(), [KubernetesConstants.K8sEdgeDeviceLabel] = KubeUtils.SanitizeLabelValue(this.resourceName.DeviceId), [KubernetesConstants.K8sEdgeHubNameLabel] = KubeUtils.SanitizeLabelValue(this.resourceName.Hostname) }); var desiredServices = modules .Select(module => this.serviceMapper.CreateService(moduleIdentities[module.Name], module, labels[module.Name])) .Where(service => service.HasValue) .Select(service => service.OrDefault()) .ToList(); V1ServiceList currentServices = await this.client.ListNamespacedServiceAsync(this.deviceNamespace, labelSelector : this.deploymentSelector); await this.ManageServices(currentServices, desiredServices); var desiredDeployments = modules .Select(module => this.deploymentMapper.CreateDeployment(moduleIdentities[module.Name], module, labels[module.Name])) .ToList(); V1DeploymentList currentDeployments = await this.client.ListNamespacedDeploymentAsync(this.deviceNamespace, labelSelector : this.deploymentSelector); await this.ManageDeployments(currentDeployments, desiredDeployments); var desiredServiceAccounts = modules .Select(module => this.serviceAccountMapper.CreateServiceAccount(moduleIdentities[module.Name], labels[module.Name])) .ToList(); V1ServiceAccountList currentServiceAccounts = await this.client.ListNamespacedServiceAccountAsync(this.deviceNamespace, labelSelector : this.deploymentSelector); await this.ManageServiceAccounts(currentServiceAccounts, desiredServiceAccounts); return(desiredModules); }
async Task ManageServiceAccounts(V1ServiceAccountList existing, IReadOnlyCollection <V1ServiceAccount> desired) { // find difference between desired and existing service accounts var diff = FindServiceAccountDiff(desired, existing.Items); // Update all service accounts that are in both lists var updatingTasks = diff.Updated .Select( update => { Events.UpdateServiceAccount(update.To); this.serviceAccountMapper.UpdateServiceAccount(update.To, update.From); return(this.client.ReplaceNamespacedServiceAccountAsync(update.To, update.To.Metadata.Name, this.deviceNamespace)); }); await Task.WhenAll(updatingTasks); // Delete only those existing service accounts that are not in in desired list of common names var removingTasks = diff.Removed .Select( name => { Events.DeleteServiceAccount(name); return(this.client.DeleteNamespacedServiceAccountAsync(name, this.deviceNamespace)); }); await Task.WhenAll(removingTasks); // Add only those desired service account that are not in the list of common names var addingTasks = diff.Added .Select( account => { Events.CreateServiceAccount(account); return(this.client.CreateNamespacedServiceAccountAsync(account, this.deviceNamespace)); }); await Task.WhenAll(addingTasks); }
private async void AssertNoMatchingServiceAccounts(string deviceSelector, string moduleName) { V1ServiceAccountList currentServiceAccounts = await this.client.ListServiceAccountsAsync(deviceSelector); Assert.Single(currentServiceAccounts.Items, sa => sa.Metadata.Name == moduleName); }
private async void AssertNoServiceAccountsExist(string deviceSelector) { V1ServiceAccountList currentServiceAccounts = await this.client.ListServiceAccountsAsync(deviceSelector); Assert.Empty(currentServiceAccounts.Items); }
public async Task <EdgeDeploymentStatus> DeployModulesAsync(ModuleSet desiredModules, ModuleSet currentModules) { try { var moduleIdentities = await this.moduleIdentityLifecycleManager.GetModuleIdentitiesAsync(desiredModules, currentModules); // having desired modules an no module identities means that we are unable to obtain a list of module identities if (desiredModules.Modules.Any() && !moduleIdentities.Any()) { Events.NoModuleIdentities(); return(EdgeDeploymentStatus.Failure("Unable to obtain identities for desired modules")); } var labels = desiredModules.Modules .ToDictionary( module => module.Key, module => new Dictionary <string, string> { [KubernetesConstants.K8sEdgeModuleLabel] = moduleIdentities[module.Key].DeploymentName(), [KubernetesConstants.K8sEdgeDeviceLabel] = KubeUtils.SanitizeLabelValue(this.resourceName.DeviceId), [KubernetesConstants.K8sEdgeHubNameLabel] = KubeUtils.SanitizeLabelValue(this.resourceName.Hostname) }); var deviceOnlyLabels = new Dictionary <string, string> { [KubernetesConstants.K8sEdgeDeviceLabel] = KubeUtils.SanitizeLabelValue(this.resourceName.DeviceId), [KubernetesConstants.K8sEdgeHubNameLabel] = KubeUtils.SanitizeLabelValue(this.resourceName.Hostname) }; var desiredServices = desiredModules.Modules .Select(module => this.serviceMapper.CreateService(moduleIdentities[module.Key], (KubernetesModule)module.Value, labels[module.Key])) .FilterMap() .ToList(); V1ServiceList currentServices = await this.client.ListNamespacedServiceAsync(this.deviceNamespace, labelSelector : this.deploymentSelector); await this.ManageServices(currentServices, desiredServices); var desiredDeployments = desiredModules.Modules .Select(module => this.deploymentMapper.CreateDeployment(moduleIdentities[module.Key], (KubernetesModule)module.Value, labels[module.Key])) .ToList(); V1DeploymentList currentDeployments = await this.client.ListNamespacedDeploymentAsync(this.deviceNamespace, labelSelector : this.deploymentSelector); await this.ManageDeployments(currentDeployments, desiredDeployments); var desiredPvcs = desiredModules.Modules .Select(module => this.pvcMapper.CreatePersistentVolumeClaims((KubernetesModule)module.Value, deviceOnlyLabels)) .FilterMap() .SelectMany(x => x) .Distinct(KubernetesPvcByValueEqualityComparer); // Modules may use PVCs created by the user, we get all PVCs and then work on ours. V1PersistentVolumeClaimList currentPvcList = await this.client.ListNamespacedPersistentVolumeClaimAsync(this.deviceNamespace); await this.ManagePvcs(currentPvcList, desiredPvcs); var desiredServiceAccounts = desiredModules.Modules .Select(module => this.serviceAccountMapper.CreateServiceAccount((KubernetesModule)module.Value, moduleIdentities[module.Key], labels[module.Key])) .ToList(); V1ServiceAccountList currentServiceAccounts = await this.client.ListNamespacedServiceAccountAsync(this.deviceNamespace, labelSelector : this.deploymentSelector); await this.ManageServiceAccounts(currentServiceAccounts, desiredServiceAccounts); return(EdgeDeploymentStatus.Success("Successfully deployed")); } catch (HttpOperationException e) { Events.DeployModulesException(e); return(EdgeDeploymentStatus.Failure(e)); } }