public void CreatedFromPreLoadedConfig()
        {
            var k8sConfig = KubernetesClientConfiguration.LoadKubeConfig(new FileInfo("assets/kubeconfig.yml"), useRelativePaths: false);
            var cfg       = KubernetesClientConfiguration.BuildConfigFromConfigObject(k8sConfig);

            Assert.NotNull(cfg.Host);
        }
Exemplo n.º 2
0
        public void SetK8SConfiguration(string config)
        {
            K8SConfiguration = KubernetesClientConfiguration.LoadKubeConfig(config.ToStream());
            Context          = K8SConfiguration.CurrentContext;

            RaisePropertyChanged(State.ConfigNotification);
        }
        public void ContextPreferencesExtensionsMergeWithDuplicates()
        {
            var path = Path.GetFullPath("assets/kubeconfig.preferences-extensions.yml");

            var cfg = KubernetesClientConfiguration.LoadKubeConfig(new FileInfo[] { new FileInfo(path), new FileInfo(path) });

            Assert.Equal(1, cfg.Extensions.Count);
            Assert.Equal(1, cfg.Preferences.Count);
        }
        public void LoadKubeConfigExplicitFilePath()
        {
            var txt         = File.ReadAllText("assets/kubeconfig.yml");
            var expectedCfg = Yaml.LoadFromString <K8SConfiguration>(txt);

            var cfg = KubernetesClientConfiguration.LoadKubeConfig("assets/kubeconfig.yml");

            Assert.NotNull(cfg);
            AssertConfigEqual(expectedCfg, cfg);
        }
        public void ContextFromSecondWorks()
        {
            var firstPath  = Path.GetFullPath("assets/kubeconfig.no-current-context.yml");
            var secondPath = Path.GetFullPath("assets/kubeconfig.no-user.yml");

            var cfg = KubernetesClientConfiguration.LoadKubeConfig(new FileInfo[] { new FileInfo(firstPath), new FileInfo(secondPath) });

            // green-user
            Assert.NotNull(cfg.CurrentContext);
        }
        public void LoadSameKubeConfigFromEnvironmentVariableUnmodified()
        {
            var txt         = File.ReadAllText("assets/kubeconfig.yml");
            var expectedCfg = Yaml.LoadFromString <K8SConfiguration>(txt);

            var fileInfo = new FileInfo(Path.GetFullPath("assets/kubeconfig.yml"));

            var cfg = KubernetesClientConfiguration.LoadKubeConfig(new FileInfo[] { fileInfo, fileInfo });

            AssertConfigEqual(expectedCfg, cfg);
        }
        public void LoadKubeConfigWithAdditionalProperties()
        {
            var txt         = File.ReadAllText("assets/kubeconfig.additional-properties.yml");
            var expectedCfg = Yaml.LoadFromString <K8SConfiguration>(txt);

            var fileInfo = new FileInfo(Path.GetFullPath("assets/kubeconfig.additional-properties.yml"));

            var cfg = KubernetesClientConfiguration.LoadKubeConfig(new FileInfo[] { fileInfo, fileInfo });

            AssertConfigEqual(expectedCfg, cfg);
        }
        public void LoadKubeConfigFileInfo()
        {
            var filePath    = "assets/kubeconfig.yml";
            var txt         = File.ReadAllText(filePath);
            var expectedCfg = Yaml.LoadFromString <K8SConfiguration>(txt);

            var fileInfo = new FileInfo(filePath);
            var cfg      = KubernetesClientConfiguration.LoadKubeConfig(fileInfo);

            Assert.NotNull(cfg);
            AssertConfigEqual(expectedCfg, cfg);
        }
        public void AlwaysPicksFirstOccurence()
        {
            var firstPath  = Path.GetFullPath("assets/kubeconfig.no-cluster.yml");
            var secondPath = Path.GetFullPath("assets/kubeconfig.no-context.yml");

            var cfg = KubernetesClientConfiguration.LoadKubeConfig(new FileInfo[] { new FileInfo(firstPath), new FileInfo(secondPath) });

            var user = cfg.Users.Where(u => u.Name == "green-user").Single();

            Assert.NotNull(user.UserCredentials.Password);
            Assert.Null(user.UserCredentials.ClientCertificate);
        }
        public void MergeKubeConfigNoDuplicates()
        {
            var firstPath  = Path.GetFullPath("assets/kubeconfig.as-user-extra.yml");
            var secondPath = Path.GetFullPath("assets/kubeconfig.yml");

            var cfg = KubernetesClientConfiguration.LoadKubeConfig(new FileInfo[] { new FileInfo(firstPath), new FileInfo(secondPath) });

            // Merged file has 6 users now.
            Assert.Equal(6, cfg.Users.Count());
            Assert.Equal(5, cfg.Clusters.Count());
            Assert.Equal(5, cfg.Contexts.Count());
        }
Exemplo n.º 11
0
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddRazorPages();
            services.AddServerSideBlazor();


            try
            {
                KubernetesClientConfiguration.LoadKubeConfig();
            }
            catch (Exception e)
            {
                _hasStartupFailed      = true;
                _startupFailureMessage = e.ToString();
            }

            if (_hasStartupFailed)
            {
                return;
            }

            services.AddTransient(provider =>
            {
                var configFile = KubernetesClientConfiguration.LoadKubeConfig();

                configFile.CurrentContext =
                    InMemoryUserPreferencesStore.CurrentContextName ?? configFile.CurrentContext;
                var config = KubernetesClientConfiguration.BuildConfigFromConfigObject(configFile);

                return(new Kubernetes(config));
            });
            services.AddSingleton <KubernetesHelper>();
            services.AddSingleton <EntityReferenceUrlBuilder>();
            services.AddSingleton <KubernetesCommandLineBuilder>();
            services.AddBlazoredSessionStorage();
            services.AddClipboard();

            services.AddBootstrapCss();
            var fusion = services.AddFusion();

            services.AddSingleton(c => new UpdateDelayer.Options()
            {
                // Default update delayer options
                Delay = TimeSpan.FromSeconds(0.1),
            });
            fusion.AddComputeService <IKubeConfigLoader, KubeConfigLoader>();
            RegisterFusionDb(fusion);
            services.AttributeBased().AddServicesFrom(Assembly.GetExecutingAssembly());
        }
        public void LoadKubeConfigStream()
        {
            var filePath    = "assets/kubeconfig.yml";
            var txt         = File.ReadAllText(filePath);
            var expectedCfg = Yaml.LoadFromString <K8SConfiguration>(txt);

            var fileInfo = new FileInfo(filePath);
            K8SConfiguration cfg;

            using (var stream = fileInfo.OpenRead())
            {
                cfg = KubernetesClientConfiguration.LoadKubeConfig(stream);
            }

            Assert.NotNull(cfg);
            AssertConfigEqual(expectedCfg, cfg);
        }
Exemplo n.º 13
0
        public List <Context> GetAllContexts()
        {
            var k8SConfig = KubernetesClientConfiguration.LoadKubeConfig();
            var contexts  = new List <Context>();

            foreach (var c in k8SConfig.Contexts)
            {
                var context = new Context
                {
                    Cluster   = c.ContextDetails.Cluster,
                    Name      = c.Name,
                    Namespace = string.IsNullOrEmpty(c.Namespace) ? "" : c.Namespace,
                    User      = c.ContextDetails.User,
                    Current   = c.ContextDetails.Cluster == k8SConfig.CurrentContext ? "*" : ""
                };

                contexts.Add(context);
            }

            return(contexts);
        }
Exemplo n.º 14
0
        public State(ILogger <State> logger)
        {
            Logger = logger;

            try
            {
                K8SConfiguration = KubernetesClientConfiguration.LoadKubeConfig();
                Context          = K8SConfiguration.CurrentContext;
            } catch (KubeConfigException)
            {
                Logger.LogInformation("No kube config found");

                K8SConfiguration = new K8SConfiguration
                {
                    FileName = "config",
                    Clusters = new List <Cluster>()
                    {
                        new Cluster()
                        {
                            Name = "localhost:8001", ClusterEndpoint = new ClusterEndpoint()
                            {
                                Server = "http://localhost:8001"
                            }
                        }
                    },
                    Contexts = new List <Context>()
                    {
                        new Context()
                        {
                            Name = "localhost:8001", ContextDetails = new ContextDetails()
                            {
                                Cluster = "localhost:8001"
                            }
                        }
                    }
                };

                Context = "localhost:8001";
            }
        }
Exemplo n.º 15
0
        static async Task <List <Pod> > GetAllPods(string[] excludeClusters, int timeoutSeconds)
        {
            var config   = KubernetesClientConfiguration.LoadKubeConfig();
            var clusters = new List <string>();

            foreach (var context in config.Contexts.OrderBy(c => c.Name))
            {
                if (excludeClusters.Any(e => context.Name.Contains(e)))
                {
                    Console.WriteLine($"Excluding cluster: '{context.Name}'");
                    continue;
                }
                clusters.Add(context.Name);
            }

            var allpods = new List <Task <List <Pod> > >();

            foreach (var cluster in clusters)
            {
                KubernetesClientConfiguration clientConfig;
                try
                {
                    clientConfig = KubernetesClientConfiguration.BuildConfigFromConfigObject(config, cluster);
                }
                catch (KubeConfigException ex)
                {
                    Console.WriteLine($"Ignoring cluster (invalid config): '{cluster}': {ex.Message}");
                    continue;
                }

                Console.WriteLine($"Connecting to: {clientConfig.Host} ({cluster})");
                IKubernetes client = new Kubernetes(clientConfig);

                allpods.Add(GetPods(client, cluster, timeoutSeconds));
            }

            await Task.WhenAll(allpods);

            return(allpods.SelectMany(t => t.Result).ToList());
        }
Exemplo n.º 16
0
        public override async Task ExecuteAsync(OutputContext output, ApplicationBuilder application, ServiceBuilder service)
        {
            var bindings = service.Outputs.OfType <ComputedBindings>().FirstOrDefault();

            if (bindings is null)
            {
                return;
            }

            foreach (var binding in bindings.Bindings)
            {
                if (binding is SecretInputBinding secretInputBinding)
                {
                    if (!Secrets.Add(secretInputBinding.Name))
                    {
                        output.WriteDebugLine($"Already validated secret '{secretInputBinding.Name}'.");
                        continue;
                    }

                    output.WriteDebugLine($"Validating secret '{secretInputBinding.Name}'.");

                    var config = KubernetesClientConfiguration.BuildDefaultConfig();

                    // Workaround for https://github.com/kubernetes-client/csharp/issues/372
                    var store   = KubernetesClientConfiguration.LoadKubeConfig();
                    var context = store.Contexts.Where(c => c.Name == config.CurrentContext).FirstOrDefault();
                    config.Namespace ??= context?.ContextDetails?.Namespace;

                    var kubernetes = new Kubernetes(config);

                    try
                    {
                        var result = await kubernetes.ReadNamespacedSecretWithHttpMessagesAsync(secretInputBinding.Name, config.Namespace ?? "default");

                        output.WriteInfoLine($"Found existing secret '{secretInputBinding.Name}'.");
                        continue;
                    }
                    catch (HttpOperationException ex) when(ex.Response.StatusCode == HttpStatusCode.NotFound)
                    {
                        // The kubernetes client uses exceptions for 404s.
                    }
                    catch (Exception ex)
                    {
                        output.WriteDebugLine("Failed to query secret.");
                        output.WriteDebugLine(ex.ToString());
                        throw new CommandException("Unable connect to kubernetes.", ex);
                    }

                    if (Force)
                    {
                        output.WriteDebugLine("Skipping because force was specified.");
                        continue;
                    }

                    if (!Interactive)
                    {
                        throw new CommandException(
                                  $"The secret '{secretInputBinding.Name}' used for service '{secretInputBinding.Service.Name}' is missing from the deployment environment. " +
                                  $"Rerun the command with --interactive to specify the value interactively, or with --force to skip validation. Alternatively " +
                                  $"use the following command to manually create the secret." + System.Environment.NewLine +
                                  $"kubectl create secret generic {secretInputBinding.Name} --from-literal=connectionstring=<value>");
                    }

                    // If we get here then we should create the sceret.
                    var text = output.Prompt($"Enter the connection string to use for service '{secretInputBinding.Service.Name}'", allowEmpty: true);
                    if (string.IsNullOrWhiteSpace(text))
                    {
                        output.WriteAlways($"Skipping creation of secret for '{secretInputBinding.Service.Name}'. This may prevent creation of pods until secrets are created.");
                        output.WriteAlways($"Manually create a secret with:");
                        output.WriteAlways($"kubectl create secret generic {secretInputBinding.Name} --from-literal=connectionstring=<value>");
                        continue;
                    }

                    var secret = new V1Secret(type: "Opaque", stringData: new Dictionary <string, string>()
                    {
                        { "connectionstring", text },
                    });
                    secret.Metadata      = new V1ObjectMeta();
                    secret.Metadata.Name = secretInputBinding.Name;

                    output.WriteDebugLine($"Creating secret '{secret.Metadata.Name}'.");

                    try
                    {
                        await kubernetes.CreateNamespacedSecretWithHttpMessagesAsync(secret, config.Namespace ?? "default");

                        output.WriteInfoLine($"Created secret '{secret.Metadata.Name}'.");
                    }
                    catch (Exception ex)
                    {
                        output.WriteDebugLine("Failed to create secret.");
                        output.WriteDebugLine(ex.ToString());
                        throw new CommandException("Failed to create secret.", ex);
                    }
                }
            }

            var yaml = service.Outputs.OfType <IYamlManifestOutput>().ToArray();

            if (yaml.Length == 0)
            {
                output.WriteDebugLine($"No yaml manifests found for service '{service.Name}'. Skipping.");
                return;
            }

            using var tempFile = TempFile.Create();
            output.WriteDebugLine($"Writing output to '{tempFile.FilePath}'.");

            {
                using var stream = File.OpenWrite(tempFile.FilePath);
                using var writer = new StreamWriter(stream, Encoding.UTF8, bufferSize: -1, leaveOpen: true);
                var yamlStream = new YamlStream(yaml.Select(y => y.Yaml));
                yamlStream.Save(writer, assignAnchors: false);
            }

            // kubectl apply logic is implemented in the client in older versions of k8s. The capability
            // to get the same behavior in the server isn't present in every version that's relevant.
            //
            // https://kubernetes.io/docs/reference/using-api/api-concepts/#server-side-apply
            //
            output.WriteDebugLine("Running 'kubectl apply'.");
            output.WriteCommandLine("kubectl", $"apply -f \"{tempFile.FilePath}\"");
            var capture  = output.Capture();
            var exitCode = await Process.ExecuteAsync(
                $"kubectl",
                $"apply -f \"{tempFile.FilePath}\"",
                System.Environment.CurrentDirectory,
                stdOut : capture.StdOut,
                stdErr : capture.StdErr);

            output.WriteDebugLine($"Done running 'kubectl apply' exit code: {exitCode}");
            if (exitCode != 0)
            {
                throw new CommandException("'kubectl apply' failed.");
            }

            output.WriteInfoLine($"Deployed service '{service.Name}'.");
        }