Esempio n. 1
0
        async Task <(ModuleSet current, Exception ex)> GetCurrentModuleSetAsync(CancellationToken token)
        {
            ModuleSet current = null;
            Exception ex      = null;

            try
            {
                current = await this.environment.GetModulesAsync(token);
            }
            catch (Exception e) when(!e.IsFatal())
            {
                ex = e;
            }

            return(current, ex);
        }
Esempio n. 2
0
        public async Task ReconcileAsync(CancellationToken token)
        {
            ModuleSet moduleSetToReport = null;

            using (await this.reconcileLock.LockAsync(token))
            {
                try
                {
                    Events.StartingReconcile();
                    (ModuleSet current, DeploymentConfigInfo deploymentConfigInfo, Exception exception) = await this.GetReconcileData(token);

                    moduleSetToReport = current;
                    if (exception != null)
                    {
                        ExceptionDispatchInfo.Capture(exception).Throw();
                    }

                    DeploymentConfig deploymentConfig = deploymentConfigInfo.DeploymentConfig;
                    if (deploymentConfig.Equals(DeploymentConfig.Empty))
                    {
                        this.status = DeploymentStatus.Success;
                    }
                    else
                    {
                        ModuleSet desiredModuleSet = deploymentConfig.GetModuleSet();
                        _ = Task.Run(() => this.availabilityMetric.ComputeAvailability(desiredModuleSet, current))
                            .ContinueWith(t => Events.UnknownFailure(t.Exception), TaskContinuationOptions.OnlyOnFaulted)
                            .ConfigureAwait(false);

                        // TODO - Update this logic to create identities only when needed, in the Command factory, instead of creating all the identities
                        // up front here. That will allow handling the case when only the state of the system has changed (say one module crashes), and
                        // no new identities need to be created. This will simplify the logic to allow EdgeAgent to work when offline.
                        // But that required ModuleSet.Diff to be updated to include modules updated by deployment, and modules updated by state change.
                        IImmutableDictionary <string, IModuleIdentity> identities = await this.moduleIdentityLifecycleManager.GetModuleIdentitiesAsync(desiredModuleSet, current);

                        Plan plan = await this.planner.PlanAsync(desiredModuleSet, current, deploymentConfig.Runtime, identities);

                        if (plan.IsEmpty)
                        {
                            this.status = DeploymentStatus.Success;
                        }
                        else
                        {
                            try
                            {
                                bool result = await this.planRunner.ExecuteAsync(deploymentConfigInfo.Version, plan, token);

                                await this.UpdateCurrentConfig(deploymentConfigInfo);

                                if (result)
                                {
                                    this.status = DeploymentStatus.Success;
                                }
                            }
                            catch (Exception ex) when(!ex.IsFatal())
                            {
                                Events.PlanExecutionFailed(ex);
                                await this.UpdateCurrentConfig(deploymentConfigInfo);

                                throw;
                            }
                        }
                    }
                }
                catch (Exception ex) when(!ex.IsFatal())
                {
                    switch (ex)
                    {
                    case ConfigEmptyException _:
                        this.status = new DeploymentStatus(DeploymentStatusCode.ConfigEmptyError, ex.Message);
                        Events.EmptyConfig(ex);
                        break;

                    case InvalidSchemaVersionException _:
                        this.status = new DeploymentStatus(DeploymentStatusCode.InvalidSchemaVersion, ex.Message);
                        Events.InvalidSchemaVersion(ex);
                        break;

                    case ConfigFormatException _:
                        this.status = new DeploymentStatus(DeploymentStatusCode.ConfigFormatError, ex.Message);
                        Events.InvalidConfigFormat(ex);
                        break;

                    default:
                        this.status = new DeploymentStatus(DeploymentStatusCode.Failed, ex.Message);
                        Events.UnknownFailure(ex);
                        break;
                    }
                }

                await this.reporter.ReportAsync(token, moduleSetToReport, await this.environment.GetRuntimeInfoAsync(), this.currentConfig.Version, this.status);

                Events.FinishedReconcile();
            }
        }
Esempio n. 3
0
        public async Task ReconcileAsync(CancellationToken token)
        {
            Option <DeploymentStatus> status = Option.None <DeploymentStatus>();
            ModuleSet moduleSetToReport      = null;

            using (await this.reconcileLock.LockAsync(token))
            {
                try
                {
                    (ModuleSet current, DeploymentConfigInfo deploymentConfigInfo, Exception exception) = await this.GetReconcileData(token);

                    moduleSetToReport = current;
                    if (exception != null)
                    {
                        throw exception;
                    }

                    DeploymentConfig deploymentConfig = deploymentConfigInfo.DeploymentConfig;
                    if (deploymentConfig != DeploymentConfig.Empty)
                    {
                        ModuleSet desiredModuleSet = deploymentConfig.GetModuleSet();
                        IImmutableDictionary <string, IModuleIdentity> identities = await this.moduleIdentityLifecycleManager.GetModuleIdentitiesAsync(desiredModuleSet, current);

                        Plan plan = await this.planner.PlanAsync(desiredModuleSet, current, deploymentConfig.Runtime, identities);

                        if (!plan.IsEmpty)
                        {
                            try
                            {
                                bool result = await this.planRunner.ExecuteAsync(deploymentConfigInfo.Version, plan, token);

                                await this.UpdateCurrentConfig(deploymentConfigInfo);

                                if (result)
                                {
                                    status = Option.Some(DeploymentStatus.Success);
                                }
                            }
                            catch (Exception ex) when(!ex.IsFatal())
                            {
                                Events.PlanExecutionFailed(ex);
                                await this.UpdateCurrentConfig(deploymentConfigInfo);

                                throw;
                            }
                        }
                    }
                    else
                    {
                        status = Option.Some(DeploymentStatus.Success);
                    }
                }
                catch (Exception ex) when(!ex.IsFatal())
                {
                    switch (ex)
                    {
                    case ConfigEmptyException _:
                        status = Option.Some(new DeploymentStatus(DeploymentStatusCode.ConfigEmptyError, ex.Message));
                        Events.EmptyConfig(ex);
                        break;

                    case InvalidSchemaVersionException _:
                        status = Option.Some(new DeploymentStatus(DeploymentStatusCode.InvalidSchemaVersion, ex.Message));
                        Events.InvalidSchemaVersion(ex);
                        break;

                    case ConfigFormatException _:
                        status = Option.Some(new DeploymentStatus(DeploymentStatusCode.ConfigFormatError, ex.Message));
                        Events.InvalidConfigFormat(ex);
                        break;

                    default:
                        status = Option.Some(new DeploymentStatus(DeploymentStatusCode.Failed, ex.Message));
                        Events.UnknownFailure(ex);
                        break;
                    }
                }
                await this.reporter.ReportAsync(token, moduleSetToReport, await this.environment.GetRuntimeInfoAsync(), this.currentConfig.Version, status);
            }
        }