public async void ReadDeploymentConfigFromSecret()
        {
            ISerde <DeploymentConfigInfo> serde = this.GetSerde();

            var secretData = new Dictionary <string, byte[]>
            {
                ["backup.json"] = System.Text.Encoding.UTF8.GetBytes(serde.Serialize(ValidConfigInfo1))
            };
            var secret   = new V1Secret(data: secretData);
            var response = new HttpOperationResponse <V1Secret>()
            {
                Body     = secret,
                Response = new HttpResponseMessage(HttpStatusCode.OK)
            };

            var client = new Mock <IKubernetes>(MockBehavior.Strict);

            client.Setup(c => c.ReadNamespacedSecretWithHttpMessagesAsync(DefaultSecretName, DefaultNamespace, It.IsAny <bool?>(), It.IsAny <bool?>(), null, null, It.IsAny <CancellationToken>()))
            .ReturnsAsync(response);

            var backupSource         = new DeploymentSecretBackup(DefaultSecretName, DefaultNamespace, DefaultOwner, serde, client.Object);
            var deploymentConfigInfo = await backupSource.ReadFromBackupAsync();

            string returnedJson = serde.Serialize(deploymentConfigInfo);
            string expectedJson = serde.Serialize(ValidConfigInfo1);

            Assert.Equal(expectedJson, returnedJson, ignoreCase: true);
            client.VerifyAll();
        }
        public async void BackupDeploymentDoesNotThrowOnFailure()
        {
            ISerde <DeploymentConfigInfo> serde = this.GetSerde();

            string expectedJson   = serde.Serialize(ValidConfigInfo1);
            var    readSecretData = new Dictionary <string, byte[]>
            {
                ["backup.json"] = System.Text.Encoding.UTF8.GetBytes(serde.Serialize(ValidConfigInfo2))
            };
            var readSecret        = new V1Secret(data: readSecretData);
            var replaceSecretData = new Dictionary <string, byte[]>
            {
                ["backup.json"] = System.Text.Encoding.UTF8.GetBytes(expectedJson)
            };
            var replaceSecret = new V1Secret(data: readSecretData);
            var readResponse  = new HttpOperationResponse <V1Secret>()
            {
                Body     = readSecret,
                Response = new HttpResponseMessage(HttpStatusCode.OK)
            };

            var client = new Mock <IKubernetes>(MockBehavior.Strict);

            client.Setup(c => c.ReadNamespacedSecretWithHttpMessagesAsync(DefaultSecretName, DefaultNamespace, It.IsAny <bool?>(), It.IsAny <bool?>(), null, null, It.IsAny <CancellationToken>()))
            .ReturnsAsync(readResponse);
            client.Setup(c => c.ReplaceNamespacedSecretWithHttpMessagesAsync(It.IsAny <V1Secret>(), DefaultSecretName, DefaultNamespace, null, null, null, null, It.IsAny <CancellationToken>()))
            .ThrowsAsync(new HttpOperationException("Not Permitted"));

            var backupSource = new DeploymentSecretBackup(DefaultSecretName, DefaultNamespace, DefaultOwner, serde, client.Object);
            await backupSource.BackupDeploymentConfigAsync(ValidConfigInfo1);

            client.VerifyAll();
        }
        public async void DeserializeFaillureReturnsEmptyConfig()
        {
            ISerde<DeploymentConfigInfo> serde = this.GetSerde();

            var secretData = new Dictionary<string, byte[]>
            {
                ["backup.json"] = System.Text.Encoding.UTF8.GetBytes("{}")
            };
            var secret = new V1Secret(data: secretData);
            var response = new HttpOperationResponse<V1Secret>()
            {
                Body = secret,
                Response = new HttpResponseMessage(HttpStatusCode.OK)
            };

            var client = new Mock<IKubernetes>(MockBehavior.Strict);
            client.Setup(c => c.ReadNamespacedSecretWithHttpMessagesAsync(
                    DefaultSecretName,
                    DefaultNamespace,
                    It.IsAny<string>(), // pretty
                    null, // customHeaders
                    It.IsAny<CancellationToken>()))
                .ReturnsAsync(response);

            var backupSource = new DeploymentSecretBackup(DefaultSecretName, DefaultNamespace, DefaultOwner, serde, client.Object);
            var deploymentConfigInfo = await backupSource.ReadFromBackupAsync();

            Assert.NotNull(deploymentConfigInfo);
            Assert.Equal(DeploymentConfigInfo.Empty, deploymentConfigInfo);
            client.VerifyAll();
        }
        public async void NullSecretreturnsEmptyConfig()
        {
            ISerde<DeploymentConfigInfo> serde = this.GetSerde();

            var response = new HttpOperationResponse<V1Secret>()
            {
                Body = null,
                Response = new HttpResponseMessage(HttpStatusCode.OK)
            };

            var client = new Mock<IKubernetes>(MockBehavior.Strict);
            client.Setup(c => c.ReadNamespacedSecretWithHttpMessagesAsync(
                    DefaultSecretName,
                    DefaultNamespace,
                    It.IsAny<string>(), // pretty
                    null, // customHeaders
                    It.IsAny<CancellationToken>()))
                .ReturnsAsync(response);

            var backupSource = new DeploymentSecretBackup(DefaultSecretName, DefaultNamespace, DefaultOwner, serde, client.Object);
            var deploymentConfigInfo = await backupSource.ReadFromBackupAsync();

            Assert.NotNull(deploymentConfigInfo);
            Assert.Equal(DeploymentConfigInfo.Empty, deploymentConfigInfo);
            client.VerifyAll();
        }
        public async void BackupDeploymentConfigReplacesSecret()
        {
            ISerde<DeploymentConfigInfo> serde = this.GetSerde();

            string expectedJson = serde.Serialize(ValidConfigInfo1);
            var readSecretData = new Dictionary<string, byte[]>
            {
                ["backup.json"] = System.Text.Encoding.UTF8.GetBytes(serde.Serialize(ValidConfigInfo2))
            };
            var readSecret = new V1Secret(data: readSecretData);
            var replaceSecretData = new Dictionary<string, byte[]>
            {
                ["backup.json"] = System.Text.Encoding.UTF8.GetBytes(expectedJson)
            };
            var replaceSecret = new V1Secret(data: readSecretData);
            var readResponse = new HttpOperationResponse<V1Secret>()
            {
                Body = readSecret,
                Response = new HttpResponseMessage(HttpStatusCode.OK)
            };
            var replaceResponse = new HttpOperationResponse<V1Secret>()
            {
                Body = replaceSecret,
                Response = new HttpResponseMessage(HttpStatusCode.OK)
            };

            byte[] receivedData = default(byte[]);
            var client = new Mock<IKubernetes>(MockBehavior.Strict);
            client.Setup(c => c.ReadNamespacedSecretWithHttpMessagesAsync(
                    DefaultSecretName,
                    DefaultNamespace,
                    It.IsAny<string>(), // pretty
                    null, // customHeaders
                    It.IsAny<CancellationToken>()))
                .ReturnsAsync(readResponse);
            client.Setup(c => c.ReplaceNamespacedSecretWithHttpMessagesAsync(
                    It.IsAny<V1Secret>(),
                    DefaultSecretName,
                    DefaultNamespace,
                    null, // dryRun
                    null, // fieldmanager
                    null, // pretty
                    null, // customHeaders
                    It.IsAny<CancellationToken>()))
                .Callback((V1Secret body, string name, string namespaceParameter, string dryRun, string fieldManager, string pretty, Dictionary<string, List<string>> customHeaders, CancellationToken cancellationToken) =>
                {
                    Assert.True(body.Data != null);
                    Assert.True(body.Data.TryGetValue("backup.json", out receivedData));
                })
                .ReturnsAsync(replaceResponse);

            var backupSource = new DeploymentSecretBackup(DefaultSecretName, DefaultNamespace, DefaultOwner, serde, client.Object);
            await backupSource.BackupDeploymentConfigAsync(ValidConfigInfo1);

            string backupJson = System.Text.Encoding.UTF8.GetString(receivedData);

            Assert.Equal(expectedJson, backupJson, ignoreCase: true);
            client.VerifyAll();
        }
        public void NameIsSecretName()
        {
            var serde  = Mock.Of <ISerde <DeploymentConfigInfo> >();
            var client = Mock.Of <IKubernetes>();

            var backupSource = new DeploymentSecretBackup(DefaultSecretName, DefaultNamespace, DefaultOwner, serde, client);

            Assert.Equal(DefaultSecretName, backupSource.Name);
        }
        protected override void Load(ContainerBuilder builder)
        {
            // IKubernetesClient
            builder.Register(
                c =>
            {
                if (this.enableServiceCallTracing)
                {
                    // enable tracing of k8s requests made by the client
                    var loggerFactory = c.Resolve <ILoggerFactory>();
                    ILogger logger    = loggerFactory.CreateLogger(typeof(Kubernetes));
                    ServiceClientTracing.IsEnabled = true;
                    ServiceClientTracing.AddTracingInterceptor(new DebugTracer(logger));
                }

                // load the k8s config from KUBECONFIG or $HOME/.kube/config or in-cluster if its available
                KubernetesClientConfiguration kubeConfig = Option.Maybe(Environment.GetEnvironmentVariable("KUBECONFIG"))
                                                           .Else(() => Option.Maybe(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".kube", "config")))
                                                           .Filter(File.Exists)
                                                           .Map(path => KubernetesClientConfiguration.BuildConfigFromConfigFile(path))
                                                           .GetOrElse(KubernetesClientConfiguration.InClusterConfig);

                return(new Kubernetes(kubeConfig));
            })
            .As <IKubernetes>()
            .SingleInstance();

            // IModuleClientProvider
            builder.Register(
                c => new ModuleClientProvider(
                    c.Resolve <ISdkModuleClientProvider>(),
                    this.upstreamProtocol,
                    this.proxy,
                    this.productInfo.OrDefault(),
                    this.closeOnIdleTimeout,
                    this.idleTimeout))
            .As <IModuleClientProvider>()
            .SingleInstance();

            // IModuleManager
            builder.Register(c => new ModuleManagementHttpClient(this.managementUri, this.apiVersion, Core.Constants.EdgeletClientApiVersion))
            .As <IModuleManager>()
            .As <IIdentityManager>()
            .As <IDeviceManager>()
            .SingleInstance();

            // IModuleIdentityLifecycleManager
            var identityBuilder = new ModuleIdentityProviderServiceBuilder(this.resourceName.Hostname, this.resourceName.DeviceId, this.edgeDeviceHostName);

            builder.Register(c => new KubernetesModuleIdentityLifecycleManager(c.Resolve <IIdentityManager>(), identityBuilder, this.workloadUri))
            .As <IModuleIdentityLifecycleManager>()
            .SingleInstance();

            // CombinedKubernetesConfigProvider
            builder.Register(
                c =>
            {
                bool enableKubernetesExtensions = this.experimentalFeatures.Enabled && this.experimentalFeatures.EnableExtensions;
                return(new CombinedKubernetesConfigProvider(this.dockerAuthConfig, this.workloadUri, this.managementUri, enableKubernetesExtensions));
            })
            .As <ICombinedConfigProvider <CombinedKubernetesConfig> >()
            .SingleInstance();

            // ICommandFactory
            builder.Register(
                c =>
            {
                var metricsProvider     = c.Resolve <IMetricsProvider>();
                var loggerFactory       = c.Resolve <ILoggerFactory>();
                ICommandFactory factory = new KubernetesCommandFactory();
                factory = new MetricsCommandFactory(factory, metricsProvider);
                factory = new LoggingCommandFactory(factory, loggerFactory);
                return(Task.FromResult(factory));
            })
            .As <Task <ICommandFactory> >()
            .SingleInstance();

            // IPlanner
            builder.Register(
                async c =>
            {
                var configProvider             = c.Resolve <ICombinedConfigProvider <CombinedKubernetesConfig> >();
                ICommandFactory commandFactory = await c.Resolve <Task <ICommandFactory> >();
                IPlanner planner = new KubernetesPlanner(
                    this.resourceName,
                    this.deviceSelector,
                    this.deviceNamespace,
                    c.Resolve <IKubernetes>(),
                    commandFactory,
                    configProvider,
                    this.moduleOwner);
                return(planner);
            })
            .As <Task <IPlanner> >()
            .SingleInstance();

            // KubernetesRuntimeInfoProvider
            builder.Register(c => new KubernetesRuntimeInfoProvider(this.deviceNamespace, c.Resolve <IKubernetes>(), c.Resolve <IModuleManager>()))
            .As <IRuntimeInfoProvider>()
            .As <IRuntimeInfoSource>()
            .SingleInstance();

            // Task<IBackupSource>
            builder.Register(
                c =>
            {
                var serde = c.Resolve <ISerde <DeploymentConfigInfo> >();
                IDeploymentBackupSource backupSource = new DeploymentSecretBackup(Constants.EdgeAgentBackupName, this.deviceNamespace, this.moduleOwner, serde, c.Resolve <IKubernetes>());
                return(Task.FromResult(backupSource));
            })
            .As <Task <IDeploymentBackupSource> >()
            .SingleInstance();

            // KubernetesDeploymentProvider
            builder.Register(
                c => new KubernetesDeploymentMapper(
                    this.deviceNamespace,
                    this.edgeDeviceHostName,
                    this.proxyImage,
                    this.proxyImagePullSecretName,
                    this.proxyConfigPath,
                    this.proxyConfigVolumeName,
                    this.proxyConfigMapName,
                    this.proxyTrustBundlePath,
                    this.proxyTrustBundleVolumeName,
                    this.proxyTrustBundleConfigMapName,
                    this.defaultMapServiceType,
                    this.persistentVolumeName,
                    this.storageClassName,
                    this.persistentVolumeClaimSizeMb,
                    this.apiVersion,
                    this.workloadUri,
                    this.managementUri,
                    this.runAsNonRoot,
                    this.enableServiceCallTracing,
                    this.experimentalFeatures.GetEnvVars()))
            .As <IKubernetesDeploymentMapper>();

            // KubernetesServiceMapper
            builder.Register(c => new KubernetesServiceMapper(this.defaultMapServiceType))
            .As <IKubernetesServiceMapper>();

            // KubernetesPvcMapper
            builder.Register(c => new KubernetesPvcMapper(this.persistentVolumeName, this.storageClassName, this.persistentVolumeClaimSizeMb.OrDefault()))
            .As <IKubernetesPvcMapper>();

            // KubernetesServiceAccountProvider
            builder.Register(c => new KubernetesServiceAccountMapper())
            .As <IKubernetesServiceAccountMapper>();

            // EdgeDeploymentController
            builder.Register(
                c =>
            {
                IEdgeDeploymentController watchOperator = new EdgeDeploymentController(
                    this.resourceName,
                    this.deviceSelector,
                    this.deviceNamespace,
                    c.Resolve <IKubernetes>(),
                    c.Resolve <IModuleIdentityLifecycleManager>(),
                    c.Resolve <IKubernetesServiceMapper>(),
                    c.Resolve <IKubernetesDeploymentMapper>(),
                    c.Resolve <IKubernetesPvcMapper>(),
                    c.Resolve <IKubernetesServiceAccountMapper>());

                return(watchOperator);
            })
            .As <IEdgeDeploymentController>()
            .SingleInstance();

            // IEdgeDeploymentOperator
            builder.Register(
                c =>
            {
                IEdgeDeploymentOperator watchOperator = new EdgeDeploymentOperator(
                    this.resourceName,
                    this.deviceNamespace,
                    c.Resolve <IKubernetes>(),
                    c.Resolve <IEdgeDeploymentController>());

                return(watchOperator);
            })
            .As <IEdgeDeploymentOperator>()
            .SingleInstance();

            // IKubernetesEnvironmentOperator
            builder.Register(
                c =>
            {
                IKubernetesEnvironmentOperator watchOperator = new KubernetesEnvironmentOperator(
                    this.deviceNamespace,
                    c.Resolve <IRuntimeInfoSource>(),
                    c.Resolve <IKubernetes>());

                return(watchOperator);
            })
            .As <IKubernetesEnvironmentOperator>()
            .SingleInstance();

            // Task<IEnvironmentProvider>
            builder.Register(
                async c =>
            {
                CancellationTokenSource tokenSource = new CancellationTokenSource(SystemInfoTimeout);
                var moduleStateStore     = await c.Resolve <Task <IEntityStore <string, ModuleState> > >();
                var restartPolicyManager = c.Resolve <IRestartPolicyManager>();
                IRuntimeInfoProvider runtimeInfoProvider       = c.Resolve <IRuntimeInfoProvider>();
                IEnvironmentProvider dockerEnvironmentProvider = await DockerEnvironmentProvider.CreateAsync(runtimeInfoProvider, moduleStateStore, restartPolicyManager, tokenSource.Token);
                return(dockerEnvironmentProvider);
            })
            .As <Task <IEnvironmentProvider> >()
            .SingleInstance();
        }