public void HashCode() { var hash1 = KubeContextName.Parse("user1@cluster/test").GetHashCode(); var hash2 = KubeContextName.Parse("user2@cluster/test").GetHashCode(); Assert.NotEqual(hash1, hash2); }
public void ToString_Standard() { Assert.Equal("context/namespace", KubeContextName.Parse("context/namespace").ToString()); Assert.Equal("context/test", KubeContextName.Parse("context/TEST").ToString()); Assert.Equal("context", KubeContextName.Parse("context/default").ToString()); Assert.Equal("context", KubeContextName.Parse("context/DEFAULT").ToString()); }
public void EqualOperator_Standard() { Assert.True(KubeContextName.Parse("cluster") == KubeContextName.Parse("cluster")); Assert.True(KubeContextName.Parse("cluster") == KubeContextName.Parse("cluster/default")); Assert.True((KubeContextName)null == (KubeContextName)null); Assert.False(KubeContextName.Parse("cluster/test") == KubeContextName.Parse("bar/test")); Assert.False(KubeContextName.Parse("cluster/test") == KubeContextName.Parse("cluster/foobar")); Assert.False(KubeContextName.Parse("cluster/test") == (KubeContextName)null); Assert.False((KubeContextName)null == KubeContextName.Parse("cluster/foobar")); }
public void Equal_Standard() { Assert.True(KubeContextName.Parse("cluster").Equals(KubeContextName.Parse("cluster"))); Assert.True(KubeContextName.Parse("cluster").Equals(KubeContextName.Parse("cluster/default"))); Assert.True(KubeContextName.Parse("cluster/default").Equals(KubeContextName.Parse("CLUSTER/DEFAULT"))); Assert.False(KubeContextName.Parse("cluster/default").Equals(KubeContextName.Parse("BAR/default"))); Assert.False(KubeContextName.Parse("cluster/default").Equals(KubeContextName.Parse("cluster/FOOBAR"))); Assert.False(KubeContextName.Parse("cluster/default").Equals(null)); Assert.False(KubeContextName.Parse("cluster/default").Equals("not a config name type")); }
public void Equal() { Assert.True(KubeContextName.Parse("user@cluster").Equals(KubeContextName.Parse("user@cluster"))); Assert.True(KubeContextName.Parse("user@cluster").Equals(KubeContextName.Parse("user@cluster/default"))); Assert.False(KubeContextName.Parse("user@cluster/default").Equals(KubeContextName.Parse("FOO@cluster/default"))); Assert.False(KubeContextName.Parse("user@cluster/default").Equals(KubeContextName.Parse("user@BAR/default"))); Assert.False(KubeContextName.Parse("user@cluster/default").Equals(KubeContextName.Parse("user@cluster/FOOBAR"))); Assert.False(KubeContextName.Parse("user@cluster/default").Equals(null)); Assert.False(KubeContextName.Parse("user@cluster/default").Equals("not a config name type")); }
public void HashCode_Standard() { var hash1 = KubeContextName.Parse("cluster1/test").GetHashCode(); var hash2 = KubeContextName.Parse("cluster2/test").GetHashCode(); Assert.NotEqual(hash1, hash2); hash1 = KubeContextName.Parse("cluster/test1").GetHashCode(); hash2 = KubeContextName.Parse("cluster/test2").GetHashCode(); Assert.NotEqual(hash1, hash2); }
public void Equal_NeonKube() { Assert.True(KubeContextName.Parse("user@cluster").Equals(KubeContextName.Parse("user@cluster"))); Assert.True(KubeContextName.Parse("user@cluster").Equals(KubeContextName.Parse("user@cluster/default"))); Assert.True(KubeContextName.Parse("user@cluster/default").Equals(KubeContextName.Parse("USER@CLUSTER/DEFAULT"))); Assert.False(KubeContextName.Parse("user@cluster/default").Equals(KubeContextName.Parse("FOO@cluster/default"))); Assert.False(KubeContextName.Parse("user@cluster/default").Equals(KubeContextName.Parse("user@BAR/default"))); Assert.False(KubeContextName.Parse("user@cluster/default").Equals(KubeContextName.Parse("user@cluster/FOOBAR"))); Assert.False(KubeContextName.Parse("user@cluster/default").Equals(null)); Assert.False(KubeContextName.Parse("user@cluster/default").Equals("not a config name type")); }
public void NotEqualOperator_NeonKube() { Assert.False(KubeContextName.Parse("user@cluster") != KubeContextName.Parse("user@cluster")); Assert.False(KubeContextName.Parse("user@cluster") != KubeContextName.Parse("user@cluster/default")); Assert.False((KubeContextName)null != (KubeContextName)null); Assert.True(KubeContextName.Parse("user@cluster/test") != KubeContextName.Parse("foo@cluster/test")); Assert.True(KubeContextName.Parse("user@cluster/test") != KubeContextName.Parse("user@bar/test")); Assert.True(KubeContextName.Parse("user@cluster/test") != KubeContextName.Parse("user@cluster/foobar")); Assert.True(KubeContextName.Parse("user@cluster/test") != (KubeContextName)null); Assert.True((KubeContextName)null != KubeContextName.Parse("user@cluster/foobar")); }
public void EqualOperator() { Assert.True(KubeContextName.Parse("user@cluster") == KubeContextName.Parse("user@cluster")); Assert.True(KubeContextName.Parse("user@cluster") == KubeContextName.Parse("user@cluster/default")); Assert.True((KubeContextName)null == (KubeContextName)null); Assert.False(KubeContextName.Parse("user@cluster/test") == KubeContextName.Parse("foo@cluster/test")); Assert.False(KubeContextName.Parse("user@cluster/test") == KubeContextName.Parse("user@bar/test")); Assert.False(KubeContextName.Parse("user@cluster/test") == KubeContextName.Parse("user@cluster/foobar")); Assert.False(KubeContextName.Parse("user@cluster/test") == (KubeContextName)null); Assert.False((KubeContextName)null == KubeContextName.Parse("user@cluster/foobar")); }
/// <inheritdoc/> public override void Run(CommandLine commandLine) { KubeConfigContext context = null; KubeContextName contextName = null; if (commandLine.Arguments.Length > 0) { contextName = KubeContextName.Parse(commandLine.Arguments.FirstOrDefault()); } if (contextName != null) { context = KubeHelper.Config.GetContext(contextName); if (context == null) { Console.Error.WriteLine($"*** ERROR: Context [{contextName}] not found."); Program.Exit(1); } } else { context = KubeHelper.CurrentContext; if (context == null) { Console.Error.WriteLine($"*** ERROR: You are not logged into a cluster."); Program.Exit(1); } contextName = (KubeContextName)context.Name; } if (!commandLine.HasOption("--force") && !Program.PromptYesNo($"*** Are you sure you want to remove: {contextName}?")) { return; } if (KubeHelper.CurrentContextName == contextName) { Console.WriteLine($"Logging out of: {contextName}"); KubeHelper.Desktop.Logout().Wait(); } KubeHelper.Config.RemoveContext(context); Console.WriteLine($"Removed: {contextName}"); // Notify the desktop application. KubeHelper.Desktop.UpdateUIAsync().Wait(); }
public void ParseStandard_WithError() { Assert.Throws <FormatException>(() => KubeContextName.Parse(null)); Assert.Throws <FormatException>(() => KubeContextName.Parse("")); var tooLong = new string('a', 254); Assert.Throws <FormatException>(() => KubeContextName.Parse("user@")); // Missing cluster Assert.Throws <FormatException>(() => KubeContextName.Parse("user@/namespace")); // Missing cluster Assert.Throws <FormatException>(() => KubeContextName.Parse($"user@{tooLong}/namespace")); // Cluster is too long Assert.Throws <FormatException>(() => KubeContextName.Parse($"user@cluster/{tooLong}")); // Namespace is too long Assert.Throws <FormatException>(() => KubeContextName.Parse("user@cluster_name/namespace")); // Cluster has bad character Assert.Throws <FormatException>(() => KubeContextName.Parse("user@cluster/namespace_name")); // Namespace has bad character }
/// <inheritdoc/> public override void Run(CommandLine commandLine) { if (commandLine.HasHelpOption || commandLine.Arguments.Length == 0) { Console.WriteLine(usage); Program.Exit(0); } Console.Error.WriteLine(); var currentContext = KubeHelper.CurrentContext; var newContextName = KubeContextName.Parse(commandLine.Arguments.First()); // Ensure that the new context exists. if (KubeHelper.Config.GetContext(newContextName) == null) { Console.Error.WriteLine($"*** Context [{newContextName}] not found."); Program.Exit(1); } // Check whether we're already logged into the cluster. if (KubeHelper.CurrentContext != null && newContextName == KubeContextName.Parse(KubeHelper.CurrentContext.Name)) { Console.Error.WriteLine($"*** You are already logged into: {newContextName}"); Program.Exit(0); } // Logout of the current cluster. if (currentContext != null) { Console.Error.WriteLine($"Logging out of [{currentContext.Name}]."); KubeHelper.SetCurrentContext((string)null); } // ...and log into the new context. KubeHelper.SetCurrentContext(newContextName); Console.WriteLine($"*** Logged into [{newContextName}]."); // Notify the desktop application. KubeHelper.Desktop.Login().Wait(); }
public void ParseStandard() { // Verify that the standard components are parsed correctly (without the "USER@"). var name = KubeContextName.Parse("cluster/namespace"); Assert.Null(name.User); Assert.Equal("cluster", name.Cluster); Assert.Equal("namespace", name.Namespace); name = KubeContextName.Parse("mine/my-space"); Assert.Null(name.User); Assert.Equal("mine", name.Cluster); Assert.Equal("my-space", name.Namespace); name = KubeContextName.Parse("cluster"); Assert.Null(name.User); Assert.Equal("cluster", name.Cluster); Assert.Equal("default", name.Namespace); }
public void ParseNeonKube() { // Verify that the neonKUBE components are parsed correctly. var name = KubeContextName.Parse("user@cluster/namespace"); Assert.Equal("user", name.User); Assert.Equal("cluster", name.Cluster); Assert.Equal("namespace", name.Namespace); name = KubeContextName.Parse("me@mine/my-space"); Assert.Equal("me", name.User); Assert.Equal("mine", name.Cluster); Assert.Equal("my-space", name.Namespace); name = KubeContextName.Parse("user@cluster"); Assert.Equal("user", name.User); Assert.Equal("cluster", name.Cluster); Assert.Equal("default", name.Namespace); }
public void Parse() { // Verify that the components are parsed correctly: var name = KubeContextName.Parse("user@cluster/namespace"); Assert.Equal("user", name.User); Assert.Equal("cluster", name.Cluster); Assert.Equal("namespace", name.Namespace); name = KubeContextName.Parse("me@mine/my-space"); Assert.Equal("me", name.User); Assert.Equal("mine", name.Cluster); Assert.Equal("my-space", name.Namespace); name = KubeContextName.Parse("user@cluster"); Assert.Equal("user", name.User); Assert.Equal("cluster", name.Cluster); Assert.Equal("default", name.Namespace); // Ensure that the components are converted to lowercase. name = KubeContextName.Parse("USER@CLUSTER/NAMESPACE"); Assert.Equal("user", name.User); Assert.Equal("cluster", name.Cluster); Assert.Equal("namespace", name.Namespace); name = new KubeContextName("USER", "CLUSTER", "NAMESPACE"); Assert.Equal("user", name.User); Assert.Equal("cluster", name.Cluster); Assert.Equal("namespace", name.Namespace); }
/// <summary> /// <para> /// Deploys a new test cluster as specified by the cluster definition passed or connects /// to a cluster previously deployed by this method when the cluster definition of the /// existing cluster and the definition passed here are the same. /// </para> /// </summary> /// <param name="clusterDefinition">The cluster definition model.</param> /// <param name="options"> /// Optionally specifies the options that <see cref="ClusterFixture"/> will use to /// manage the test cluster. /// </param> /// <returns> /// <para> /// The <see cref="TestFixtureStatus"/>: /// </para> /// <list type="table"> /// <item> /// <term><see cref="TestFixtureStatus.Disabled"/></term> /// <description> /// Returned when cluster unit testing is disabled due to the <c>NEON_CLUSTER_TESTING</c> environment /// variable not being present on the current machine which means that <see cref="TestHelper.IsClusterTestingEnabled"/> /// returns <c>false</c>. /// </description> /// </item> /// <item> /// <term><see cref="TestFixtureStatus.Started"/></term> /// <description> /// Returned when one of the <c>Start()</c> methods is called for the first time for the fixture /// instance, indicating that an existing cluster has been connected or a new cluster has been deployed. /// </description> /// </item> /// <item> /// <term><see cref="TestFixtureStatus.AlreadyRunning"/></term> /// <description> /// Returned when one of the <c>Start()</c> methods has already been called by your test /// class instance. /// </description> /// </item> /// </list> /// </returns> /// <exception cref="NeonKubeException">Thrown when the test cluster could not be deployed.</exception> /// <remarks> /// <para> /// <b>IMPORTANT:</b> Only one <see cref="ClusterFixture"/> can be run at a time on /// any one computer. This is due to the fact that cluster state like the kubeconfig, /// neonKUBE logins, logs and other files will be written to <b>~/.neonkube/spaces/$fixture/*</b> /// so multiple fixture instances will be confused when trying to manage these same files. /// </para> /// <para> /// This means that not only will running <see cref="ClusterFixture"/> based tests in parallel /// within the same instance of Visual Studio fail, but running these tests in different /// Visual Studio instances will also fail. /// </para> /// </remarks> public TestFixtureStatus StartWithClusterDefinition(ClusterDefinition clusterDefinition, ClusterFixtureOptions options = null) { Covenant.Requires <ArgumentNullException>(clusterDefinition != null, nameof(clusterDefinition)); if (clusterDefinition.IsLocked) { throw new NeonKubeException("Test clusters need to be unlocked. Please set [isLocked: false] in your cluster definition."); } if (!TestHelper.IsClusterTestingEnabled) { return(TestFixtureStatus.Disabled); } if (started) { return(TestFixtureStatus.AlreadyRunning); } options ??= new ClusterFixtureOptions(); this.options = options.Clone(); if (this.Cluster != null) { return(TestFixtureStatus.AlreadyRunning); } // Set the clusterspace mode, using any previously downloaded node image unless // the user specifies a custom image. We're going to host the fixture state // files in this fixed folder: // // ~/.neonkube/spaces/$fixture/* clusterspaceFolder = KubeHelper.SetClusterSpaceMode(string.IsNullOrEmpty(options.ImageUriOrPath) ? KubeClusterspaceMode.EnabledWithSharedCache : KubeClusterspaceMode.Enabled, KubeHelper.ClusterspacePrefix("fixture")); // Figure out whether the user passed an image URI or file path to override // the default node image. var imageUriOrPath = options.ImageUriOrPath; var imageUri = (string)null; var imagePath = (string)null; if (string.IsNullOrEmpty(imageUriOrPath)) { imageUriOrPath = KubeDownloads.GetDefaultNodeImageUri(clusterDefinition.Hosting.Environment); } if (imageUriOrPath.StartsWith("http://", StringComparison.InvariantCultureIgnoreCase) || imageUriOrPath.StartsWith("https://", StringComparison.InvariantCultureIgnoreCase)) { imageUri = imageUriOrPath; } else { imagePath = imageUriOrPath; } //------------------------------------------------------------- // We need to deal with some scenarios here: // // 1. No cluster context or login exists for the target cluster. // // A conflicting cluster may still exist though, having been deployed // by another computer or perhaps the kubecontext/logins on the current // machine may have been modified. We need to be sure to remove any // conflicting resources in this case. // // 2. Cluster context and login exist on the current machine for the target // cluster but the cluster is unhealthy or locked. We'll abort for locked // clusters and remove and redeploy for unhealth clusters. // // 3. Cluster context and login exist and the cluster is healthy. In this case, // we need to compare the deployed cluster version against the current version // and remove/redeploy when the versions don't match. // // 4. Cluster context and login exist and the cluster is healthy and cluster versions // match. In this case, We'll compare the existing cluster definition with that for // the new cluster and also compare the cluster versions and if they match and // [RemoveClusterOnStart=false] we'll just use the existing cluster. // // 5. The current cluster matches the target but [RemoveClusterOnStart=true]. // We need to remove the current cluster in this case so we'll deploy a // fresh one. // Determine whether a test cluster with the same name exists and if // its cluster definition matches the test cluster's definition. ; var clusterExists = false; var clusterContextName = KubeContextName.Parse($"root@{clusterDefinition.Name}"); var clusterContext = KubeHelper.Config.GetContext(clusterContextName); var clusterLogin = KubeHelper.GetClusterLogin(clusterContextName); if (clusterContext != null && clusterLogin != null && !clusterLogin.SetupDetails.SetupPending) { clusterExists = ClusterDefinition.AreSimilar(clusterDefinition, clusterLogin.ClusterDefinition); } if (clusterExists && !options.RemoveClusterOnStart) { // It looks like the test cluster may already exist. We'll verify // that it's running, healthy, unlocked and the cluster versions match. // When all of these conditions are true, we'll use the existing cluster, // otherwise we'll remove the cluster as well as its context/login, // and deploy a new cluster below. using (var cluster = new ClusterProxy(clusterLogin.ClusterDefinition, new HostingManagerFactory())) { KubeHelper.SetCurrentContext(clusterContextName); var isLocked = cluster.IsLockedAsync().ResultWithoutAggregate(); var clusterInfo = cluster.GetClusterInfoAsync().ResultWithoutAggregate(); var clusterHealth = cluster.GetClusterHealthAsync().ResultWithoutAggregate(); if (isLocked.HasValue && isLocked.Value) { throw new NeonKubeException($"Cluster is locked: {cluster.Name}"); } if (clusterHealth.State == ClusterState.Healthy && clusterInfo.ClusterVersion == KubeVersions.NeonKube) { // We need to reset an existing cluster to ensure it's in a known state. cluster.ResetAsync().WaitWithoutAggregate(); started = true; IsRunning = true; Cluster = new ClusterProxy(KubeHelper.CurrentContext, new HostingManagerFactory()); return(TestFixtureStatus.Started); } cluster.RemoveAsync(removeOrphans: true).WaitWithoutAggregate(); } } else { // There is no known existing cluster but there still might be a cluster // deployed by another machine or fragments of a partially deployed cluster, // so we need to do a preemptive cluster remove. using (var cluster = new ClusterProxy(clusterDefinition, new HostingManagerFactory())) { cluster.RemoveAsync(removeOrphans: true).WaitWithoutAggregate(); } } // Provision the new cluster. WriteTestOutputLine($"PREPARE CLUSTER: {clusterDefinition.Name}"); try { var controller = KubeSetup.CreateClusterPrepareController( clusterDefinition: clusterDefinition, nodeImageUri: imageUri, nodeImagePath: imagePath, maxParallel: options.MaxParallel, unredacted: options.Unredacted, neonCloudHeadendUri: options.NeonCloudHeadendUri); switch (controller.RunAsync().ResultWithoutAggregate()) { case SetupDisposition.Succeeded: WriteTestOutputLine("CLUSTER PREPARE: SUCCESS"); break; case SetupDisposition.Failed: WriteTestOutputLine("CLUSTER PREPARE: FAIL"); throw new NeonKubeException("Cluster prepare failed."); case SetupDisposition.Cancelled: default: throw new NotImplementedException(); } } finally { if (options.CaptureDeploymentLogs) { CaptureDeploymentLogs(); } } // Setup the cluster. WriteTestOutputLine($"SETUP CLUSTER: {clusterDefinition.Name}"); try { var controller = KubeSetup.CreateClusterSetupController( clusterDefinition: clusterDefinition, maxParallel: options.MaxParallel, unredacted: options.Unredacted); switch (controller.RunAsync().ResultWithoutAggregate()) { case SetupDisposition.Succeeded: WriteTestOutputLine("CLUSTER SETUP: SUCCESS"); break; case SetupDisposition.Failed: WriteTestOutputLine("CLUSTER SETUP: FAILED"); throw new NeonKubeException("Cluster setup failed."); case SetupDisposition.Cancelled: default: throw new NotImplementedException(); } } finally { if (options.CaptureDeploymentLogs) { CaptureDeploymentLogs(); } } // NOTE: We just deployed brand new cluster so there's no need to reset it. started = true; IsRunning = true; Cluster = new ClusterProxy(KubeHelper.CurrentContext, new HostingManagerFactory()); return(TestFixtureStatus.Started); }
/// <inheritdoc/> public override async Task RunAsync(CommandLine commandLine) { if (commandLine.Arguments.Length > 0) { Console.Error.WriteLine("*** ERROR: Unexpected argument."); Program.Exit(1); } Console.WriteLine(); var contextName = KubernetesClientConfiguration.BuildDefaultConfig().CurrentContext; if (string.IsNullOrEmpty(contextName)) { Console.Error.WriteLine($"*** ERROR: There is no current cluster."); Program.Exit(1); } var clusterLogin = KubeHelper.GetClusterLogin(KubeContextName.Parse(contextName)); if (clusterLogin == null) { Console.Error.WriteLine($"*** ERROR: There is no current cluster or the current cluster is not a neonKUBE cluster."); Program.Exit(1); } // Handle the command line options. var all = commandLine.HasOption("--all"); var containerImages = commandLine.HasOption("--container-images"); var priorityClass = commandLine.HasOption("--priority-class"); var resources = commandLine.HasOption("--resources"); var details = commandLine.HasOption("--details"); if (all || (!containerImages && !priorityClass && !resources)) { containerImages = true; priorityClass = true; resources = true; } // Perform the requested checks. var k8s = new Kubernetes(KubernetesClientConfiguration.BuildConfigFromConfigFile(KubeHelper.KubeConfigPath)); var error = false; if (containerImages && !await ClusterChecker.CheckNodeContainerImagesAsync(clusterLogin, k8s, details: details)) { error = true; } if (priorityClass && !await ClusterChecker.CheckPodPrioritiesAsync(clusterLogin, k8s, details: details)) { error = true; } if (resources && !await ClusterChecker.CheckResourcesAsync(clusterLogin, k8s, details: details)) { error = true; } if (error) { Console.Error.WriteLine(); Console.Error.WriteLine("*** ERROR: Cluster check failed with one or more errors."); Program.Exit(1); } await Task.CompletedTask; }
/// <inheritdoc/> public override async Task RunAsync(CommandLine commandLine) { KubeConfigContext context = null; KubeContextName contextName = null; Console.WriteLine(); var force = commandLine.HasOption("--force"); if (commandLine.Arguments.Length > 0) { contextName = KubeContextName.Parse(commandLine.Arguments.FirstOrDefault()); if (!contextName.IsNeonKube) { Console.Error.WriteLine($"*** ERROR: [{contextName}] is not a neonKUBE context."); Program.Exit(1); } } if (contextName != null) { context = KubeHelper.Config.GetContext(contextName); if (context == null) { if (!force) { Console.Error.WriteLine($"*** ERROR: Context [{contextName}] not found."); Program.Exit(1); } else { KubeHelper.Config.RemoveContext(contextName); Program.Exit(0); } } } else { context = KubeHelper.CurrentContext; if (context == null) { if (!force) { Console.Error.WriteLine($"*** ERROR: You are not logged into a neonKUBE cluster."); Program.Exit(1); } else { Program.Exit(0); } } contextName = (KubeContextName)context.Name; } if (!force && !Program.PromptYesNo($"*** Are you sure you want to remove: {contextName}?")) { return; } if (KubeHelper.CurrentContextName == contextName) { Console.WriteLine($"Logging out of: {contextName}"); } KubeHelper.Config.RemoveContext(context); Console.WriteLine($"Removed: {contextName}"); Console.WriteLine(); await Task.CompletedTask; }
/// <inheritdoc/> public override async Task RunAsync(CommandLine commandLine) { KubeContextName contextName = null; var path = commandLine.Arguments.FirstOrDefault(); var rawName = commandLine.GetOption("--context"); if (rawName != null) { contextName = KubeContextName.Parse(rawName); if (!contextName.IsNeonKube) { Console.Error.WriteLine($"*** ERROR: [{contextName}] is not a neonKUBE context."); Program.Exit(1); } } else { contextName = KubeHelper.CurrentContextName; if (contextName == null) { Console.Error.WriteLine($"*** ERROR: You are not logged into a neonKUBE cluster."); Program.Exit(1); } } var context = KubeHelper.Config.GetContext(contextName); if (context == null) { Console.Error.WriteLine($"*** ERROR: Context [{contextName}] not found."); Program.Exit(1); } var cluster = KubeHelper.Config.GetCluster(context.Properties.Cluster); var user = KubeHelper.Config.GetUser(context.Properties.User); if (context == null) { Console.Error.WriteLine($"*** ERROR: Context [{contextName}] not found."); Program.Exit(1); } if (user == null) { Console.Error.WriteLine($"*** ERROR: User [{context.Properties.User}] not found."); Program.Exit(1); } var login = new ClusterLoginExport() { Cluster = cluster, Context = context, Extensions = KubeHelper.GetClusterLogin(contextName), User = user }; var yaml = NeonHelper.YamlSerialize(login); if (path == null) { Console.WriteLine(yaml); } else { File.WriteAllText(path, yaml); } await Task.CompletedTask; }
/// <inheritdoc/> public override async Task RunAsync(CommandLine commandLine) { if (commandLine.HasHelpOption || commandLine.Arguments.Length == 0) { Console.WriteLine(usage); Program.Exit(0); } Console.Error.WriteLine(); var currentContext = KubeHelper.CurrentContext; var newContextName = KubeContextName.Parse(commandLine.Arguments.First()); // Ensure that the new context exists. if (KubeHelper.Config.GetContext(newContextName) == null) { Console.Error.WriteLine($"*** Context [{newContextName}] not found."); Program.Exit(1); } // Check whether we're already logged into the cluster. if (KubeHelper.CurrentContext != null && newContextName == KubeContextName.Parse(KubeHelper.CurrentContext.Name)) { Console.Error.WriteLine($"*** You are already logged into: {newContextName}"); Program.Exit(0); } // Logout of the current cluster. if (currentContext != null) { Console.Error.WriteLine($"Logout: {currentContext.Name}..."); KubeHelper.SetCurrentContext((string)null); } // Log into the new context and then send a simple command to ensure // that cluster is ready. var orgContext = KubeHelper.CurrentContext; KubeHelper.SetCurrentContext(newContextName); Console.WriteLine($"Login: {newContextName}..."); try { using (var k8s = new Kubernetes(KubernetesClientConfiguration.BuildConfigFromConfigFile(KubeHelper.KubeConfigPath))) { await k8s.ListNamespaceAsync(); } if (!string.IsNullOrEmpty(NeonHelper.DockerCli)) { Console.WriteLine($"Login: Docker to Harbor..."); var login = KubeHelper.GetClusterLogin(KubeHelper.CurrentContextName); NeonHelper.Execute(NeonHelper.DockerCli, new object[] { "login", $"{ClusterDomain.HarborRegistry}.{login.ClusterDefinition.Domain}", "--username", "root", "--password-stdin" }, input: new StringReader(login.SsoPassword)); } } catch (Exception e) { KubeHelper.SetCurrentContext(orgContext?.Name); Console.WriteLine("*** ERROR: Cluster is not responding."); Console.WriteLine(); Console.WriteLine(NeonHelper.ExceptionError(e)); Console.WriteLine(); Program.Exit(1); } Console.WriteLine(); Console.WriteLine($"Now logged into: {newContextName}"); await Task.CompletedTask; }
/// <inheritdoc/> public override async Task RunAsync(CommandLine commandLine) { if (commandLine.Arguments.Length < 1) { Console.Error.WriteLine("*** ERROR: [root@CLUSTER-NAME] argument is required."); Program.Exit(1); } Console.WriteLine(); // Cluster prepare/setup uses the [ProfileClient] to retrieve secrets and profile values. // We need to inject an implementation for [PreprocessReader] so it will be able to // perform the lookups. NeonHelper.ServiceContainer.AddSingleton <IProfileClient>(new ProfileClient()); var contextName = KubeContextName.Parse(commandLine.Arguments[0]); var kubeCluster = KubeHelper.Config.GetCluster(contextName.Cluster); var unredacted = commandLine.HasOption("--unredacted"); var debug = commandLine.HasOption("--debug"); var check = commandLine.HasOption("--check"); var uploadCharts = commandLine.HasOption("--upload-charts") || debug; var clusterspace = commandLine.GetOption("--clusterspace"); var maxParallelOption = commandLine.GetOption("--max-parallel", "6"); var disablePending = commandLine.HasOption("--disable-pending"); if (!int.TryParse(maxParallelOption, out var maxParallel) || maxParallel <= 0) { Console.Error.WriteLine($"*** ERROR: [--max-parallel={maxParallelOption}] is not valid."); Program.Exit(1); } clusterLogin = KubeHelper.GetClusterLogin(contextName); if (clusterLogin == null) { Console.Error.WriteLine($"*** ERROR: Be sure to prepare the cluster first via: neon cluster prepare..."); Program.Exit(1); } if (string.IsNullOrEmpty(clusterLogin.SshPassword)) { Console.Error.WriteLine($"*** ERROR: No cluster node SSH password found."); Program.Exit(1); } if (kubeCluster != null && !clusterLogin.SetupDetails.SetupPending) { if (commandLine.GetOption("--force") == null && !Program.PromptYesNo($"One or more logins reference [{kubeCluster.Name}]. Do you wish to delete these?")) { Program.Exit(0); } // Remove the cluster from the kubeconfig and remove any // contexts that reference it. KubeHelper.Config.Clusters.Remove(kubeCluster); var delList = new List <KubeConfigContext>(); foreach (var context in KubeHelper.Config.Contexts) { if (context.Properties.Cluster == kubeCluster.Name) { delList.Add(context); } } foreach (var context in delList) { KubeHelper.Config.Contexts.Remove(context); } if (KubeHelper.CurrentContext != null && KubeHelper.CurrentContext.Properties.Cluster == kubeCluster.Name) { KubeHelper.Config.CurrentContext = null; } KubeHelper.Config.Save(); } kubeContext = new KubeConfigContext(contextName); KubeHelper.InitContext(kubeContext); // Create and run the cluster setup controller. var clusterDefinition = clusterLogin.ClusterDefinition; var controller = KubeSetup.CreateClusterSetupController( clusterDefinition, maxParallel: maxParallel, unredacted: unredacted, debugMode: debug, uploadCharts: uploadCharts, clusterspace: clusterspace); controller.DisablePendingTasks = disablePending; controller.StatusChangedEvent += status => { status.WriteToConsole(); }; switch (await controller.RunAsync()) { case SetupDisposition.Succeeded: var pendingGroups = controller.GetPendingGroups(); if (pendingGroups.Count > 0) { Console.WriteLine($"*** ERROR: [{pendingGroups.Count}] pending task groups have not been awaited:"); Console.WriteLine(); foreach (var groupName in pendingGroups) { Console.WriteLine($" {groupName}"); } Program.Exit(1); } Console.WriteLine(); Console.WriteLine($" [{clusterDefinition.Name}] cluster is ready."); Console.WriteLine(); if (check && !debug) { var k8s = new Kubernetes(KubernetesClientConfiguration.BuildConfigFromConfigFile(KubeHelper.KubeConfigPath)); if (!await ClusterChecker.CheckAsync(clusterLogin, k8s)) { Program.Exit(1); } } Program.Exit(0); break; case SetupDisposition.Cancelled: Console.WriteLine(" *** CANCELLED: Cluster setup was cancelled."); Console.WriteLine(); Console.WriteLine(); Program.Exit(1); break; case SetupDisposition.Failed: Console.WriteLine(); Console.WriteLine(" *** ERROR: Cluster setup failed. Examine the logs here:"); Console.WriteLine(); Console.WriteLine($" {KubeHelper.LogFolder}"); Console.WriteLine(); Program.Exit(1); break; default: throw new NotImplementedException(); } await Task.CompletedTask; }