Skip to content

Commit

Permalink
feat: add cluster
Browse files Browse the repository at this point in the history
  • Loading branch information
mr-karan committed Jan 30, 2024
1 parent ff9fe08 commit 04a40cc
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 16 deletions.
17 changes: 12 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ NAME:
nomctx - Faster way to switch across multiple Nomad clusters and namespaces

USAGE:
nomctx [global options] command [command options] [arguments...]
nomctx [global options] command [command options]

VERSION:
v0.1.1 (Commit: 2023-01-30 08:34:52 +0530 (844bef4), Build: 2023-05-25% 09:57:59 +0530)
v0.2.3 (Commit: 2023-12-05 13:09:16 +0530 (ff9fe08), Build: 2024-01-30 21:06:48 +0530)

COMMANDS:
list-clusters List all clusters
Expand All @@ -45,10 +45,11 @@ COMMANDS:
switch-namespace Switch namespace
current-context Display the current context
login Login to a cluster
add-cluster Add a new cluster to the config
help, h Shows a list of commands or help for one command

GLOBAL OPTIONS:
--config value Path to a config file to load. (default: "/home/karan/.nomctx/config.hcl")
--config value Path to a config file to load. (default: "/Users/karan/.nomctx/config.hcl")
--help, -h show help
--version, -v print the version
```
Expand Down Expand Up @@ -84,6 +85,12 @@ See [Persist variables](#persist-variables) section for more details on how to p

If you don't have `fzf`, you can use switch manually with `set-cluster=<>` and `set-namespace=<>` commands.

#### Add a Cluster

```bash
nomctx add-cluster --cluster=<name> [--addr=<address>] [--token=<token>] [--namespace=<namespace>] [--region=<region>] [--auth-method=<method>]
```

#### List all clusters

```bash
Expand Down Expand Up @@ -167,7 +174,7 @@ NOMAD_REGION=paris
Here's a sample config file which shows 2 clusters: `dev` and `prod`:

```hcl
clusters "dev" {
cluster "dev" {
address = "http://127.0.0.1:4646"
namespace = "default"
}
Expand All @@ -180,7 +187,7 @@ cluster "uat" {
}
}
clusters "prod" {
cluster "prod" {
address = "http://10.0.0.3:4646"
namespace = "blue"
region = "blr"
Expand Down
94 changes: 94 additions & 0 deletions cmd/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,14 @@ import (
"encoding/json"
"errors"
"fmt"
"os"
"os/exec"

"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/hclparse"
"github.com/hashicorp/hcl/v2/hclwrite"
"github.com/urfave/cli/v2"
"github.com/zclconf/go-cty/cty"
)

// handleListClusters lists all the configured clusters.
Expand Down Expand Up @@ -181,3 +186,92 @@ func handleCurrentCtx(c *cli.Context) error {
fmt.Fprintf(c.App.Writer, "Cluster: %s\nNamespace: %s\n", context.Cluster, context.Namespace)
return nil
}

func handleAddCluster(c *cli.Context) error {
// Parse the flags
cluster := c.String("cluster")
addr := c.String("addr")
token := c.String("token")
namespace := c.String("namespace")
region := c.String("region")
authMethod := c.String("auth-method")

// Read the existing config file as a string
configBytes, err := os.ReadFile(defaultConfigFilePath)
if err != nil {
return fmt.Errorf("unable to read the config file: %v", err)
}

// Use hclparse to check if the cluster already exists
parser := hclparse.NewParser()
f, diags := parser.ParseHCL(configBytes, defaultConfigFilePath)
if diags.HasErrors() {
return fmt.Errorf("failed to parse config file: %s", diags.Error())
}

// Prepare the schema for parsing the body content
var contentSchema = &hcl.BodySchema{
Blocks: []hcl.BlockHeaderSchema{
{
Type: "cluster",
LabelNames: []string{"name"},
},
},
}

// Parse the body content of the file
content, diags := f.Body.Content(contentSchema)
if diags.HasErrors() {
return fmt.Errorf("failed to parse body content: %s", diags.Error())
}

// Check if the cluster already exists
for _, block := range content.Blocks {
if block.Type == "cluster" && len(block.Labels) > 0 && block.Labels[0] == cluster {
return fmt.Errorf("cluster '%s' already exists", cluster)
}
}

// Parse the config file using hclwrite for modification
hclFile, diags := hclwrite.ParseConfig(configBytes, defaultConfigFilePath, hcl.InitialPos)
if diags.HasErrors() {
return fmt.Errorf("failed to parse config file for writing: %s", diags.Error())
}

// Check if the last token is a newline, if not, add one
tokens := hclFile.Bytes()
if len(tokens) > 0 && tokens[len(tokens)-1] != '\n' {
hclFile.Body().AppendNewline()
}

// Append the new cluster block to the existing content
clusterBlock := hclFile.Body().AppendNewBlock("cluster", []string{cluster})
clusterBody := clusterBlock.Body()
clusterBody.SetAttributeValue("address", cty.StringVal(addr))
if token != "" {
clusterBody.SetAttributeValue("token", cty.StringVal(token))
}
if namespace != "" {
clusterBody.SetAttributeValue("namespace", cty.StringVal(namespace))
}
if region != "" {
clusterBody.SetAttributeValue("region", cty.StringVal(region))
}
if authMethod != "" {
authBlock := clusterBody.AppendNewBlock("auth", nil)
authBody := authBlock.Body()
authBody.SetAttributeValue("method", cty.StringVal(authMethod))
authBody.SetAttributeValue("provider", cty.StringVal("nomad"))
}

// Format the HCL file before writing
formattedBytes := hclwrite.Format(hclFile.Bytes())

// Write the updated config back to the file
err = os.WriteFile(defaultConfigFilePath, formattedBytes, 0644)
if err != nil {
return err
}

return nil
}
3 changes: 1 addition & 2 deletions cmd/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package main

import (
"fmt"
"io/ioutil"
"os"
"path/filepath"

Expand All @@ -21,7 +20,7 @@ func persistContext(context ContextCfg) error {
return err
}

if err := ioutil.WriteFile(contextFilePath, []byte(contextFileContent), 0644); err != nil {
if err := os.WriteFile(contextFilePath, []byte(contextFileContent), 0644); err != nil {
return err
}

Expand Down
33 changes: 33 additions & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,39 @@ func main() {
},
Action: handleLogin,
},
{
Name: "add-cluster",
Usage: "Add a new cluster to the config",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "cluster",
Required: true,
Usage: "Name of the cluster",
},
&cli.StringFlag{
Name: "addr",
Required: true,
Usage: "Address of the cluster",
},
&cli.StringFlag{
Name: "token",
Usage: "Token for the cluster",
},
&cli.StringFlag{
Name: "namespace",
Usage: "Namespace for the cluster",
},
&cli.StringFlag{
Name: "region",
Usage: "Region of the cluster",
},
&cli.StringFlag{
Name: "auth-method",
Usage: "Auth method for the cluster",
},
},
Action: handleAddCluster,
},
},
Version: buildString,
}
Expand Down
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ go 1.18

require (
github.com/hashicorp/hcl/v2 v2.19.1
github.com/urfave/cli/v2 v2.26.0
github.com/urfave/cli/v2 v2.27.1
github.com/zclconf/go-cty v1.14.2
)

require (
Expand All @@ -15,7 +16,6 @@ require (
github.com/kr/pretty v0.2.0 // indirect
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
github.com/zclconf/go-cty v1.14.1 // indirect
github.com/xrash/smetrics v0.0.0-20231213231151-1d8dd44e695e // indirect
golang.org/x/text v0.14.0 // indirect
)
12 changes: 6 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTS
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/urfave/cli/v2 v2.26.0 h1:3f3AMg3HpThFNT4I++TKOejZO8yU55t3JnnSr4S4QEI=
github.com/urfave/cli/v2 v2.26.0/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
github.com/zclconf/go-cty v1.14.1 h1:t9fyA35fwjjUMcmL5hLER+e/rEPqrbCK1/OSE4SI9KA=
github.com/zclconf/go-cty v1.14.1/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE=
github.com/urfave/cli/v2 v2.27.1 h1:8xSQ6szndafKVRmfyeUMxkNUJQMjL1F2zmsZ+qHpfho=
github.com/urfave/cli/v2 v2.27.1/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
github.com/xrash/smetrics v0.0.0-20231213231151-1d8dd44e695e h1:+SOyEddqYF09QP7vr7CgJ1eti3pY9Fn3LHO1M1r/0sI=
github.com/xrash/smetrics v0.0.0-20231213231151-1d8dd44e695e/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
github.com/zclconf/go-cty v1.14.2 h1:kTG7lqmBou0Zkx35r6HJHUQTvaRPr5bIAf3AoHS0izI=
github.com/zclconf/go-cty v1.14.2/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=

0 comments on commit 04a40cc

Please sign in to comment.