Skip to content

Commit

Permalink
initial commit for creating ipmi auth objects
Browse files Browse the repository at this point in the history
  • Loading branch information
jarededwards committed Dec 7, 2024
1 parent 6011a18 commit fd0dcfa
Show file tree
Hide file tree
Showing 7 changed files with 182 additions and 63 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ tmp/
dist/
.vscode
vendor/
*.csv
63 changes: 1 addition & 62 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,62 +1 @@
# Colony Scout

## Report

```bash
go build -o colony-scout

./colony-scout report \
--validate=k8s,cloud-init \
--type=server \ # server, node, agent
# --colony-api="http://localhost:8080" \
--token=123456 \
--cluster-id=00000000-0000-0000-0000-000000000000 \
--workflow-id=00000000-0000-0000-0000-000000000000 \
--hardware-id=00000000-0000-0000-0000-000000000000 \
--host-ip-port=192.168.0.43:6443 \
--kubeconfig=~/.kube/config \
--k3s-token=00000000-0000-0000-0000-000000000000

```

## Discovery

```bash
go build -o colony-scout

./colony-scout discovery \
# --colony-api="http://localhost:8080" \
--token=123456 \
--hardware-id=00000000-0000-0000-0000-000000000000

```

## Running test

Validate and install [kwok](https://kwok.sigs.k8s.io/)

### Run tests in CI

```bash
make test
```

### Run tests locally

```bash
make start_kwok && make test
```

## Development with Docker

### Build

```bash
docker compose build
```

### Run

```bash
docker compose up
```
# Colony
151 changes: 151 additions & 0 deletions cmd/addipmi.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
package cmd

import (
"encoding/base64"
"encoding/csv"
"fmt"
"html/template"
"os"
"path/filepath"
"strconv"
"strings"

"github.com/konstructio/colony/internal/constants"
"github.com/konstructio/colony/internal/exec"
"github.com/konstructio/colony/internal/k8s"
"github.com/konstructio/colony/internal/logger"
"github.com/konstructio/colony/manifests"
"github.com/spf13/cobra"
)

type IPMIAuth struct {
HardwareID string
IP string
Password string
Username string
InsecureTLS bool
}

func getAddIPMICommand() *cobra.Command {
var ipmiAuthFile string

getAddIPMICmd := &cobra.Command{
Use: "add-ipmi",
Short: "adds an IPMI auth to the cluster",
RunE: func(cmd *cobra.Command, _ []string) error {
log := logger.New(logger.Debug)

ctx := cmd.Context()

homeDir, err := os.UserHomeDir()
if err != nil {
return fmt.Errorf("error getting user home directory: %w", err)
}

err = exec.CreateDirIfNotExist(filepath.Join(homeDir, constants.ColonyDir, "ipmi"))
if err != nil {
return fmt.Errorf("error creating directory templates: %w", err)
}

ipmiEntries, err := parseCSV(ipmiAuthFile)
if err != nil {
return fmt.Errorf("failed to parse csv: %w", err)
}

fileTypes := []string{"machine", "secret"}

for _, entry := range ipmiEntries {
log.Infof("found entry for host ip: %q\n", entry.IP)

for _, t := range fileTypes {
file, err := manifests.IPMI.ReadFile(fmt.Sprintf("ipmi/ipmi-%s.yaml.tmpl", t))
if err != nil {
return fmt.Errorf("error reading templates file: %w", err)
}

tmpl, err := template.New("ipmi").Funcs(template.FuncMap{
"dotsToHyphens": func(s string) string {
return strings.ReplaceAll(s, ".", "-")
},
"base64Encode": func(s string) string {
return base64.StdEncoding.EncodeToString([]byte(s))
},
}).Parse(string(file))
if err != nil {
return fmt.Errorf("error parsing template: %w", err)
}

outputFile, err := os.Create(filepath.Join(homeDir, constants.ColonyDir, "ipmi", fmt.Sprintf("%s-%s.yaml", entry.HardwareID, t)))
if err != nil {
return fmt.Errorf("error creating output file: %w", err)
}
defer outputFile.Close()

err = tmpl.Execute(outputFile, entry)
if err != nil {
return fmt.Errorf("error executing template: %w", err)
}
}

var templateFiles []string

files, err := os.ReadDir(filepath.Join(homeDir, constants.ColonyDir, "ipmi"))
if err != nil {
return fmt.Errorf("failed to open directory: %w", err)
}

for _, file := range files {
content, err := os.ReadFile(filepath.Join(homeDir, constants.ColonyDir, "ipmi", file.Name()))
if err != nil {
return fmt.Errorf("failed to read file: %w", err)
}
templateFiles = append(templateFiles, string(content))
}

k8sClient, err := k8s.New(log, filepath.Join(homeDir, constants.ColonyDir, constants.KubeconfigHostPath))
if err != nil {
return fmt.Errorf("failed to create k8s client: %w", err)
}
if err := k8sClient.ApplyManifests(ctx, templateFiles); err != nil {
return fmt.Errorf("error applying templates: %w", err)
}
}

return nil
},
}
getAddIPMICmd.Flags().StringVar(&ipmiAuthFile, "ipmi-auth-file", "", "path to csv file containging IPMI auth data")

getAddIPMICmd.MarkFlagRequired("ipmi-auth-file")

return getAddIPMICmd
}

func parseCSV(filename string) ([]IPMIAuth, error) {
file, err := os.Open(filename)
if err != nil {
return nil, err

Check failure on line 127 in cmd/addipmi.go

View workflow job for this annotation

GitHub Actions / run-tests

error returned from external package is unwrapped: sig: func os.Open(name string) (*os.File, error) (wrapcheck)
}
defer file.Close()

reader := csv.NewReader(file)
records, err := reader.ReadAll()
if err != nil {
return nil, err

Check failure on line 134 in cmd/addipmi.go

View workflow job for this annotation

GitHub Actions / run-tests

error returned from external package is unwrapped: sig: func (*encoding/csv.Reader).ReadAll() (records [][]string, err error) (wrapcheck)
}

var ipmiEntries []IPMIAuth

Check failure on line 137 in cmd/addipmi.go

View workflow job for this annotation

GitHub Actions / run-tests

Consider pre-allocating `ipmiEntries` (prealloc)
for _, record := range records {
enabled, _ := strconv.ParseBool(record[4])
entry := IPMIAuth{
HardwareID: record[0],
IP: record[1],
Username: record[2],
Password: record[3],
InsecureTLS: enabled,
}
ipmiEntries = append(ipmiEntries, entry)
}

return ipmiEntries, nil
}
2 changes: 1 addition & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ func GetRootCommand() *cobra.Command {
SilenceErrors: true, // we print the errors ourselves on main
}

cmd.AddCommand(getDestroyCommand(), getInitCommand(), getVersionCommand())
cmd.AddCommand(getDestroyCommand(), getInitCommand(), getAddIPMICommand(), getVersionCommand())
return cmd
}
14 changes: 14 additions & 0 deletions manifests/ipmi/ipmi-machine.yaml.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
apiVersion: bmc.tinkerbell.org/v1alpha1
kind: Machine
metadata:
name: "{{ .IP | dotsToHyphens }}-ipmi-auth"
namespace: tink-system
labels:
colony.konstruct.io/hardware-id: "{{ .HardwareID }}"
spec:
connection:
host: "{{ .IP }}"
authSecretRef:
name: "{{ .IP | dotsToHyphens }}-ipmi-auth"
namespace: tink-system
insecureTLS: {{ .InsecureTLS }}
11 changes: 11 additions & 0 deletions manifests/ipmi/ipmi-secret.yaml.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
apiVersion: v1
kind: Secret
metadata:
name: "{{ .IP | dotsToHyphens }}-ipmi-auth"
namespace: tink-system
labels:
colony.konstruct.io/hardware-id: "{{ .HardwareID }}"
type: Opaque
data:
username: "{{ .Username | base64Encode }}"
password: "{{ .Password | base64Encode }}"
3 changes: 3 additions & 0 deletions manifests/templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,8 @@ var Colony embed.FS
//go:embed downloads/*.yaml
var Downloads embed.FS

//go:embed ipmi/*.yaml.tmpl
var IPMI embed.FS

//go:embed templates/*.yaml
var Templates embed.FS

0 comments on commit fd0dcfa

Please sign in to comment.