Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
tzneal committed Nov 24, 2021
1 parent e0bdf83 commit 5c68b82
Show file tree
Hide file tree
Showing 15 changed files with 1,609 additions and 6 deletions.
42 changes: 42 additions & 0 deletions .github/workflows/golangci-lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: golangci-lint
on:
push:
tags:
- v*
branches:
- master
- main
pull_request:
permissions:
contents: read
# Optional: allow read access to pull request. Use with `only-new-issues` option.
# pull-requests: read
jobs:
golangci:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: golangci-lint
uses: golangci/golangci-lint-action@v2
with:
# Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version
version: v1.29

# Optional: working directory, useful for monorepos
# working-directory: somedir

# Optional: golangci-lint command line arguments.
# args: --issues-exit-code=0

# Optional: show only new issues if it's a pull request. The default value is `false`.
# only-new-issues: true

# Optional: if set to true then the action will use pre-installed Go.
# skip-go-installation: true

# Optional: if set to true then the action don't cache or restore ~/go/pkg.
# skip-pkg-cache: true

# Optional: if set to true then the action don't cache or restore ~/.cache/go-build.
# skip-build-cache: true
50 changes: 50 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
on: [push, pull_request]
name: Test
jobs:
test:
strategy:
matrix:
go-version: [1.16.x, 1.17.x]
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go-version }}

- name: Checkout code
uses: actions/checkout@v2

- name: Vet
run: go vet ./...

- name: Test
run: go test ./...

test-cache:
runs-on: ubuntu-latest
steps:
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: 1.17.x
- name: Checkout code
uses: actions/checkout@v2
- uses: actions/cache@v2
with:
# In order:
# * Module download cache
# * Build cache (Linux)
# * Build cache (Mac)
# * Build cache (Windows)
path: |
~/go/pkg/mod
~/.cache/go-build
~/Library/Caches/go-build
%LocalAppData%\go-build
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Test
run: go test ./...
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.idea
supplant
12 changes: 6 additions & 6 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License
The MIT License (MIT)

Copyright (c) 2021 Todd
Copyright © 2021 Todd Neal

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand All @@ -9,13 +9,13 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
77 changes: 77 additions & 0 deletions cmd/clean.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package cmd

import (
"log"
"os"

"github.com/spf13/cobra"
"github.com/tzneal/supplant/model"
"gopkg.in/yaml.v3"
)

// cleanCmd represents the clean command
var cleanCmd = &cobra.Command{
Use: "clean",
Short: "clean removes all disabled items from a configuration file",
Long: `clean removes all disabled items. The standard workflow
is to use the 'create' commnad to construct a new configuration file
and then edit/modify it as necessary, enabling services that are to be
replaced and made available externally. Then the clean command can be
used to remove all of the disabled services for a tidier config file.`,
Args: cobra.ExactValidArgs(1),
Run: func(cmd *cobra.Command, args []string) {
inputFile := args[0]
cfg := readConfig(inputFile)

// filter out everything that is disabled
cfg.Supplant = filterSupplant(cfg.Supplant)
cfg.External = filterExternal(cfg.External)
writeConfig(cfg, inputFile)
},
}

func readConfig(inputFile string) model.Config {
f, err := os.Open(inputFile)
if err != nil {
log.Fatalf("error opening %s: %s", inputFile, err)
}
dec := yaml.NewDecoder(f)
cfg := model.Config{}
if err = dec.Decode(&cfg); err != nil {
log.Fatalf("error decoding %s: %s", inputFile, err)
}
return cfg
}

func filterSupplant(supplant []model.SupplantService) []model.SupplantService {
var ret []model.SupplantService
for _, svc := range supplant {
if svc.Enabled {
ret = append(ret, svc)
}
}
return ret
}
func filterExternal(supplant []model.ExternalService) []model.ExternalService {
var ret []model.ExternalService
for _, svc := range supplant {
if svc.Enabled {
ret = append(ret, svc)
}
}
return ret
}

func init() {
configCmd.AddCommand(cleanCmd)

// Here you will define your flags and configuration settings.

// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// cleanCmd.PersistentFlags().String("foo", "", "A help for foo")

// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// cleanCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
18 changes: 18 additions & 0 deletions cmd/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package cmd

import (
"github.com/spf13/cobra"
)

// configCmd represents the model command
var configCmd = &cobra.Command{
Use: "config",
Short: "config is the base config command",
Long: `config is the base command used to create and 'clean'
configuration files describing which services will be replaced
and which the replacing services will need to connect to.`,
}

func init() {
rootCmd.AddCommand(configCmd)
}
59 changes: 59 additions & 0 deletions cmd/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package cmd

import (
"context"
"log"
"os"

"github.com/spf13/cobra"
"github.com/tzneal/supplant/model"
"gopkg.in/yaml.v2"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
)

// createCmd represents the create command
var createCmd = &cobra.Command{
Use: "create",
Short: "create constructs a configuration file based on the cluster",
Long: `create constructs a configuration file by looking at the services
in the cluster. This is intended to provide a template to allow
easy construction of the configuration.`,
Args: cobra.ExactValidArgs(1),
Run: func(cmd *cobra.Command, args []string) {
f := cmdutil.NewFactory(kubeConfigFlags)
cs, err := f.KubernetesClientSet()
if err != nil {
log.Fatalf("error getting kubernetes client: %s", err)
}

ctx := context.Background()
svcList, err := cs.CoreV1().Services(*kubeConfigFlags.Namespace).List(ctx, metav1.ListOptions{})
if err != nil {
log.Fatalf("error listing services: %s", err)
}
cfg := model.Config{}
for _, svc := range svcList.Items {
cfg.Supplant = append(cfg.Supplant, model.MapSupplantService(svc))
cfg.External = append(cfg.External, model.MapExternalService(svc))
}

writeConfig(cfg, args[0])
},
}

func writeConfig(cfg model.Config, outputFile string) {
fo, err := os.Create(outputFile)
if err != nil {
log.Fatalf("error opening %s: %s", outputFile, err)
}
defer fo.Close()
enc := yaml.NewEncoder(fo)
if err = enc.Encode(cfg); err != nil {
log.Fatalf("error encoding config: %s", err)
}
}

func init() {
configCmd.AddCommand(createCmd)
}
36 changes: 36 additions & 0 deletions cmd/print.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package cmd

import (
"fmt"

"github.com/fatih/color"
)

func printHeader(format string, a ...interface{}) {
color.Set(color.FgGreen)
fmt.Printf("=> ")
color.Unset()
fmt.Printf(format, a...)
fmt.Println()
}

func printList(format string, a ...interface{}) {
fmt.Print(" - ")
fmt.Printf(format, a...)
fmt.Println()
}

func printInfo(format string, a ...interface{}) {
color.HiCyan(format, a...)
}

func printError(format string, a ...interface{}) {
color.Red("ERROR ")
fmt.Printf(format, a...)
fmt.Println()
}
func printWarn(format string, a ...interface{}) {
color.Yellow("WARN ")
fmt.Printf(format, a...)
fmt.Println()
}
34 changes: 34 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package cmd

import (
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"k8s.io/cli-runtime/pkg/genericclioptions"
)

// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "supplant",
Short: "A brief description of your application",
Long: `A longer description that spans multiple lines and likely contains
examples and usage of using your application. For example:
Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
}

// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
cobra.CheckErr(rootCmd.Execute())
}

var kubeConfigFlags = genericclioptions.NewConfigFlags(false)

func init() {
flags := pflag.NewFlagSet("supplant", pflag.ExitOnError)
pflag.CommandLine = flags
flags.AddFlagSet(rootCmd.PersistentFlags())
kubeConfigFlags.AddFlags(flags)
}
Loading

0 comments on commit 5c68b82

Please sign in to comment.