From f03c6cb00c32ab0e298eb67a5569ac549b2413c9 Mon Sep 17 00:00:00 2001 From: Ivan <56458442+ivan-the-terrible@users.noreply.github.com> Date: Sat, 4 May 2024 01:56:15 -0400 Subject: [PATCH] feat(segment): add talosctl --- src/engine/segment.go | 3 + src/segments/talosctl.go | 56 ++++++++++++++++++ src/segments/talosctl_test.go | 95 ++++++++++++++++++++++++++++++ themes/cloud-context.omp.json | 9 +++ themes/schema.json | 14 +++++ website/docs/segments/talosctl.mdx | 47 +++++++++++++++ website/sidebars.js | 1 + 7 files changed, 225 insertions(+) create mode 100644 src/segments/talosctl.go create mode 100644 src/segments/talosctl_test.go create mode 100644 website/docs/segments/talosctl.mdx diff --git a/src/engine/segment.go b/src/engine/segment.go index 7be2413e..8c55a265 100644 --- a/src/engine/segment.go +++ b/src/engine/segment.go @@ -240,6 +240,8 @@ const ( SWIFT SegmentType = "swift" // SYSTEMINFO writes system information (memory, cpu, load) SYSTEMINFO SegmentType = "sysinfo" + // TALOSCTL writes the talosctl context + TALOSCTL SegmentType = "talosctl" // TERRAFORM writes the terraform workspace we're currently in TERRAFORM SegmentType = "terraform" // TEXT writes a text @@ -345,6 +347,7 @@ var Segments = map[SegmentType]func() SegmentWriter{ SVN: func() SegmentWriter { return &segments.Svn{} }, SWIFT: func() SegmentWriter { return &segments.Swift{} }, SYSTEMINFO: func() SegmentWriter { return &segments.SystemInfo{} }, + TALOSCTL: func() SegmentWriter { return &segments.TalosCTL{} }, TERRAFORM: func() SegmentWriter { return &segments.Terraform{} }, TEXT: func() SegmentWriter { return &segments.Text{} }, TIME: func() SegmentWriter { return &segments.Time{} }, diff --git a/src/segments/talosctl.go b/src/segments/talosctl.go new file mode 100644 index 00000000..fe6d9fc5 --- /dev/null +++ b/src/segments/talosctl.go @@ -0,0 +1,56 @@ +package segments + +import ( + "errors" + "path/filepath" + + "github.com/jandedobbeleer/oh-my-posh/src/platform" + "github.com/jandedobbeleer/oh-my-posh/src/properties" + "gopkg.in/yaml.v3" +) + +type TalosCTL struct { + props properties.Properties + env platform.Environment + + Context string `yaml:"context"` +} + +func (t *TalosCTL) Template() string { + return " {{ .Context}} " +} + +func (t *TalosCTL) Init(props properties.Properties, env platform.Environment) { + t.props = props + t.env = env +} + +func (t *TalosCTL) Enabled() bool { + cfgDir := filepath.Join(t.env.Home(), ".talos") + configFile, err := t.getActiveConfig(cfgDir) + if err != nil { + t.env.Error(err) + return false + } + + err = yaml.Unmarshal([]byte(configFile), t) + if err != nil { + t.env.Error(err) + return false + } + + if len(t.Context) == 0 { + return false + } + + return true +} + +func (t *TalosCTL) getActiveConfig(cfgDir string) (string, error) { + activeConfigFile := filepath.Join(cfgDir, "config") + activeConfigData := t.env.FileContent(activeConfigFile) + if len(activeConfigData) == 0 { + return "", errors.New("NO ACTIVE CONFIG FOUND") + } + return activeConfigData, nil +} diff --git a/src/segments/talosctl_test.go b/src/segments/talosctl_test.go new file mode 100644 index 00000000..5c565835 --- /dev/null +++ b/src/segments/talosctl_test.go @@ -0,0 +1,95 @@ +package segments + +import ( + "path/filepath" + "testing" + + "github.com/jandedobbeleer/oh-my-posh/src/mock" + "github.com/stretchr/testify/assert" + mock2 "github.com/stretchr/testify/mock" +) + +func TestTalosctlSegment(t *testing.T) { + cases := []struct { + Case string + ActiveConfig string + ExpectedEnabled bool + ExpectedString string + }{ + { + Case: "happy path", + ExpectedEnabled: true, + ActiveConfig: "context: context-name", + ExpectedString: "context-name", + }, + { + Case: "no active config", + ExpectedEnabled: false, + }, + { + Case: "empty config", + ActiveConfig: "", + ExpectedEnabled: false, + }, + { + Case: "bad config", + ActiveConfig: "other-yaml: not-expected", + ExpectedEnabled: false, + }, + } + + for _, tc := range cases { + env := new(mock.MockedEnvironment) + env.On("Home").Return("home") + fcPath := filepath.Join("home", ".talos", "config") + env.On("FileContent", fcPath).Return(tc.ActiveConfig) + env.On("Error", mock2.Anything).Return() + talos := TalosCTL{ + env: env, + } + talos.Enabled() + assert.Equal(t, tc.ExpectedEnabled, talos.Enabled()) + if tc.ExpectedEnabled { + assert.Equal(t, tc.ExpectedString, renderTemplate(env, talos.Template(), talos), tc.Case) + } + } +} + +func TestGetTalosctlActiveConfig(t *testing.T) { + cases := []struct { + Case string + ActiveConfig string + ExpectedString string + ExpectedError string + }{ + { + Case: "happy path", + ActiveConfig: "context: context-name", + ExpectedString: "context: context-name", + }, + { + Case: "no active config", + ActiveConfig: "", + ExpectedError: "NO ACTIVE CONFIG FOUND", + }, + } + + for _, tc := range cases { + env := new(mock.MockedEnvironment) + env.On("Home").Return("home") + configPath := filepath.Join("home", ".talos") + contentPath := filepath.Join(configPath, "config") + env.On("FileContent", contentPath).Return(tc.ActiveConfig) + env.On("Error", mock2.Anything).Return() + talos := TalosCTL{ + env: env, + } + got, err := talos.getActiveConfig(configPath) + assert.Equal(t, tc.ExpectedString, got, tc.Case) + if len(tc.ExpectedError) > 0 { + assert.EqualError(t, err, tc.ExpectedError, tc.Case) + } else { + assert.NoError(t, err, tc.Case) + } + } +} diff --git a/themes/cloud-context.omp.json b/themes/cloud-context.omp.json index d2bf2627..61acfd4f 100644 --- a/themes/cloud-context.omp.json +++ b/themes/cloud-context.omp.json @@ -12,6 +12,7 @@ "error-text": "#242424", "git-text": "#238636", "kubernetes-text": "#FFBB00", + "talosctl-text": "#FF6C00", "symbol-color": "#ffffff", "timer-text": "#dd0033" }, @@ -39,6 +40,14 @@ "template": "\uf308 {{.Context}}{{if .Namespace}} \uf061 {{.Namespace}}{{end}}", "type": "kubectl" }, + { + "background": "p:background-color", + "foreground": "p:talosctl-text", + "style": "powerline", + "powerline_symbol": "\ue0b4", + "template": "\udb84\udcfe {{.Context}}", + "type": "talosctl" + }, { "background": "p:background-color", "foreground": "p:cloud-text-amazon", diff --git a/themes/schema.json b/themes/schema.json index 0d0853f6..f9e249b3 100644 --- a/themes/schema.json +++ b/themes/schema.json @@ -360,6 +360,7 @@ "strava", "svn", "swift", + "talosctl", "time", "text", "terraform", @@ -2779,6 +2780,19 @@ } } }, + { + "if": { + "properties": { + "type": { + "const": "talosctl" + } + } + }, + "then": { + "title": "Talosctl Segment", + "description": "https://ohmyposh.dev/docs/segments/talosctl" + } + }, { "if": { "properties": { diff --git a/website/docs/segments/talosctl.mdx b/website/docs/segments/talosctl.mdx new file mode 100644 index 00000000..0c2f4bcc --- /dev/null +++ b/website/docs/segments/talosctl.mdx @@ -0,0 +1,47 @@ +--- +id: talosctl +title: Talosctl Context +sidebar_label: Talosctl +--- + +## What + +Displays the currently active Talosctl context name. + +This segment leverages the `.talos/config` file generated by the [Talosctl CLI][talosctl]. +The CLI docs can be found by going to Documentation > Reference > CLI. +For example, [v1.7 CLI][CLI]. + +## Sample Configuration + +import Config from '@site/src/components/Config.js'; + + + +## Template ([info][templates]) + +:::note default template + +```template +{{ .Context }} +``` + +::: + +### Properties + +| Name | Type | Description | +| ------------ | -------- | ------------------------------------- | +| `.Context` | `string` | the current talosctl context | + + +[templates]: /docs/configuration/templates +[talosctl]: https://www.talos.dev/ +[CLI]: https://www.talos.dev/v1.7/reference/cli/ diff --git a/website/sidebars.js b/website/sidebars.js index 51ea96e6..870214be 100644 --- a/website/sidebars.js +++ b/website/sidebars.js @@ -123,6 +123,7 @@ module.exports = { "segments/svn", "segments/swift", "segments/sysinfo", + "segments/talosctl", "segments/terraform", "segments/text", "segments/time",