Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
jonas-grgt committed Jan 1, 2025
1 parent da87177 commit 8f8121f
Show file tree
Hide file tree
Showing 69 changed files with 8,931 additions and 0 deletions.
25 changes: 25 additions & 0 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: main integration build

on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]

jobs:

build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.23.2'

- name: Build
run: go build -tags prd -v ./...

- name: Test
run: go test -tags prd -v ./...
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,9 @@ go.work.sum

# env file
.env

# debug file
debug.log

# goland
.idea
235 changes: 235 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
package config

import (
"fmt"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/log"
"os"
)

type AuthMethod int

type SecurityProtocol string

const (
NoneAuthMethod AuthMethod = 0
SASLAuthMethod AuthMethod = 1
SSLSecurityProtocol SecurityProtocol = "SSL"
PlaintextSecurityProtocol SecurityProtocol = "PLAIN_TEXT"
)

type SASLConfig struct {
Username string `yaml:"username"`
Password string `yaml:"password"`
SecurityProtocol SecurityProtocol `yaml:"securityProtocol"`
}

type SchemaRegistryConfig struct {
Url string `yaml:"url"`
Username string `yaml:"username"`
Password string `yaml:"password"`
}

type Cluster struct {
Name string `yaml:"name"`
Color string `yaml:"color"`
Active bool `yaml:"active"`
BootstrapServers []string `yaml:"servers"`
SASLConfig *SASLConfig `yaml:"sasl"`
SchemaRegistry *SchemaRegistryConfig `yaml:"schema-registry"`
}

func (c *Cluster) HasSchemaRegistry() bool {
return c.SchemaRegistry != nil
}

type Config struct {
Clusters []Cluster `yaml:"clusters"`
ConfigIO ConfigIO
}

func (c *Config) HasEnvs() bool {
return len(c.Clusters) > 0
}

type SchemaRegistryDetails struct {
Url string
Username string
Password string
}

type RegistrationDetails struct {
Name string
Active bool
Color string
Host string
AuthMethod AuthMethod
SecurityProtocol SecurityProtocol
NewName *string
Username string
Password string
SchemaRegistry *SchemaRegistryDetails
}

type ClusterDeletedMsg struct {
Name string
}

type ClusterRegisteredMsg struct {
Cluster *Cluster
}

type ClusterRegisterer interface {
RegisterCluster(d RegistrationDetails) tea.Msg
}

// RegisterCluster registers a new cluster or updates an existing one in the Config.
//
// If a cluster with the same name exists, it updates its details while retaining the "Active" status (the active param
// in that case is ignored) and optionally renaming it. Otherwise, it adds the cluster to the Config.
//
// It returns a ClusterRegisteredMsg with the registered cluster.
func (c *Config) RegisterCluster(details RegistrationDetails) tea.Msg {
cluster := Cluster{
Name: details.Name,
Active: details.Active,
Color: details.Color,
BootstrapServers: []string{details.Host},
}

if details.AuthMethod == SASLAuthMethod {
cluster.SASLConfig = &SASLConfig{
Username: details.Username,
Password: details.Password,
SecurityProtocol: details.SecurityProtocol,
}
}

if details.SchemaRegistry != nil {
cluster.SchemaRegistry = &SchemaRegistryConfig{
Url: details.SchemaRegistry.Url,
Username: details.SchemaRegistry.Username,
Password: details.SchemaRegistry.Password,
}
}

// did the newly registered cluster update an existing one
var isUpdated bool

for i := range c.Clusters {
if c.Clusters[i].Name == details.Name {
isActive := c.Clusters[i].Active
c.Clusters[i] = cluster
c.Clusters[i].Active = isActive
if details.NewName != nil {
c.Clusters[i].Name = *details.NewName
}
isUpdated = true
break
}
}

// not updated, add new cluster to slice
if !isUpdated {
c.Clusters = append(c.Clusters, cluster)
}

c.flush()

return ClusterRegisteredMsg{&cluster}
}

func (c *Config) ActiveCluster() *Cluster {
for _, c := range c.Clusters {
if c.Active {
return &c
}
}
if len(c.Clusters) > 0 {
return &c.Clusters[0]
}
return nil
}

func (c *Config) flush() {
if err := c.ConfigIO.write(c); err != nil {
fmt.Println("Unable to write config file")
os.Exit(-1)
}
}

func (c *Config) SwitchCluster(name string) *Cluster {
var activeCluster *Cluster

for i := range c.Clusters {
// deactivate all clusters
c.Clusters[i].Active = false
if c.Clusters[i].Name == name {
c.Clusters[i].Active = true
activeCluster = &c.Clusters[i]
log.Debug("switched to cluster " + name)
}
}

c.flush()

return activeCluster
}

func (c *Config) DeleteCluster(name string) {
// Find the index of the cluster to delete
index := -1
for i, cluster := range c.Clusters {
if cluster.Name == name {
index = i
break
}
}

if index == -1 {
log.Warn("cluster not found: " + name)
return
}

// Check if the cluster to delete is active
isActive := c.Clusters[index].Active

// Remove the cluster
c.Clusters = append(c.Clusters[:index], c.Clusters[index+1:]...)

// Reactivate the first cluster if needed
if isActive && len(c.Clusters) > 0 {
c.Clusters[0].Active = true
}

c.flush()

log.Debug("deleted cluster: " + name)
}

func (c *Config) FindClusterByName(name string) *Cluster {
for _, cluster := range c.Clusters {
if cluster.Name == name {
return &cluster
}
}
return nil
}

type LoadedMsg struct {
Config *Config
}

func New(configIO ConfigIO) *Config {
config, err := configIO.read()
if err != nil {
fmt.Println("Error reading config file:", err)
os.Exit(-1)
}
config.ConfigIO = configIO
return config
}

func ReLoadConfig() tea.Msg {
return nil
}
Loading

0 comments on commit 8f8121f

Please sign in to comment.