예제 #1
0
        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);
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
        }
예제 #5
0
        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);
        }
예제 #6
0
        private async void AssertNoMatchingServiceAccounts(string deviceSelector, string moduleName)
        {
            V1ServiceAccountList currentServiceAccounts = await this.client.ListServiceAccountsAsync(deviceSelector);

            Assert.Single(currentServiceAccounts.Items, sa => sa.Metadata.Name == moduleName);
        }
예제 #7
0
        private async void AssertNoServiceAccountsExist(string deviceSelector)
        {
            V1ServiceAccountList currentServiceAccounts = await this.client.ListServiceAccountsAsync(deviceSelector);

            Assert.Empty(currentServiceAccounts.Items);
        }
예제 #8
0
        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));
            }
        }