253 lines
8.6 KiB
Go
253 lines
8.6 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"flag"
|
||
|
"fmt"
|
||
|
"io/ioutil"
|
||
|
"path/filepath"
|
||
|
"strings"
|
||
|
|
||
|
"gopkg.in/yaml.v2"
|
||
|
"k8s.io/apimachinery/pkg/api/errors"
|
||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||
|
"k8s.io/client-go/kubernetes"
|
||
|
"k8s.io/client-go/tools/clientcmd"
|
||
|
"k8s.io/client-go/util/homedir"
|
||
|
|
||
|
"git.martyn.berlin/martyn/helm-import/internal/exporters"
|
||
|
//
|
||
|
// Uncomment to load all auth plugins
|
||
|
// "k8s.io/client-go/plugin/pkg/client/auth"
|
||
|
//
|
||
|
// Or uncomment to load specific auth plugins
|
||
|
// _ "k8s.io/client-go/plugin/pkg/client/auth/azure"
|
||
|
// _ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
|
||
|
// _ "k8s.io/client-go/plugin/pkg/client/auth/oidc"
|
||
|
// _ "k8s.io/client-go/plugin/pkg/client/auth/openstack"
|
||
|
)
|
||
|
|
||
|
type objectFlags []string
|
||
|
|
||
|
func (i *objectFlags) String() string {
|
||
|
return strings.Join(*i, ", ")
|
||
|
}
|
||
|
|
||
|
func (i *objectFlags) Set(value string) error {
|
||
|
*i = append(*i, value)
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
type jqCommands []string
|
||
|
|
||
|
func (i *jqCommands) String() string {
|
||
|
return strings.Join(*i, ", ")
|
||
|
}
|
||
|
|
||
|
func (i *jqCommands) Set(value string) error {
|
||
|
*i = append(*i, value)
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
var deployments objectFlags
|
||
|
var services objectFlags
|
||
|
var configmaps objectFlags
|
||
|
var secrets objectFlags
|
||
|
var ingresses objectFlags
|
||
|
var namespace string
|
||
|
var noBuiltinMods bool
|
||
|
var lessOpinions bool
|
||
|
var deploymentJqCommands jqCommands
|
||
|
var serviceJqCommands jqCommands
|
||
|
var ingressJqCommands jqCommands
|
||
|
var globalJqCommands jqCommands
|
||
|
var configmapJqCommands jqCommands
|
||
|
var secretJqCommands jqCommands
|
||
|
|
||
|
type chartDef struct {
|
||
|
APIVersion string `json: "apiVersion"`
|
||
|
Name string `json: "name"`
|
||
|
Description string `json: "description"`
|
||
|
Type string `json: "type"`
|
||
|
Version string `json: "version"`
|
||
|
AppVersion string `json: "appVersion"`
|
||
|
}
|
||
|
|
||
|
var chart chartDef
|
||
|
|
||
|
func main() {
|
||
|
chartYamlFile, err := ioutil.ReadFile("Chart.yaml")
|
||
|
if err != nil {
|
||
|
panic("Run this from the chart folder, where Chart.yaml is. Error: " + err.Error())
|
||
|
}
|
||
|
err = yaml.Unmarshal(chartYamlFile, &chart)
|
||
|
if err != nil {
|
||
|
panic("Could not read the chart yaml as expected. Error: " + err.Error())
|
||
|
}
|
||
|
|
||
|
var kubeconfig *string
|
||
|
if home := homedir.HomeDir(); home != "" {
|
||
|
kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")
|
||
|
} else {
|
||
|
kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")
|
||
|
}
|
||
|
|
||
|
flag.StringVar(&namespace, "namespace", "default", "namespace to work in")
|
||
|
|
||
|
flag.Var(&deployments, "deployment", "deployment to import into the helm chart (can be specified multiple times)")
|
||
|
flag.Var(&services, "service", "service to import into the helm chart (can be specified multiple times)")
|
||
|
flag.Var(&configmaps, "configmap", "configmap to import into the helm chart (can be specified multiple times)")
|
||
|
flag.Var(&secrets, "secret", "secret to import into the helm chart (can be specified multiple times)")
|
||
|
flag.Var(&ingresses, "ingress", "ingress to import into the helm chart (can be specified multiple times)")
|
||
|
|
||
|
flag.BoolVar(&noBuiltinMods, "nobuiltinmods", false, "don't do the built-in modifications, only ones passed in by user")
|
||
|
flag.BoolVar(&lessOpinions, "lessopinions", false, "just import the objects into files, don't get opinionated")
|
||
|
|
||
|
flag.Var(&globalJqCommands, "globalJqCommands", "extra jq commands to apply to all k8s objects")
|
||
|
flag.Var(&deploymentJqCommands, "deploymentJqCommands", "extra jq commands to apply to deployments")
|
||
|
flag.Var(&serviceJqCommands, "serviceJqCommands", "extra jq commands to apply to services")
|
||
|
flag.Var(&configmapJqCommands, "configmapJqCommands", "extra jq commands to apply to configmaps")
|
||
|
flag.Var(&secretJqCommands, "secretJqCommands", "extra jq commands to apply to secrets")
|
||
|
flag.Var(&ingressJqCommands, "ingressJqCommands", "extra jq commands to apply to ingresses")
|
||
|
|
||
|
flag.Parse()
|
||
|
|
||
|
// use the current context in kubeconfig
|
||
|
config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
|
||
|
if err != nil {
|
||
|
panic(err.Error())
|
||
|
}
|
||
|
|
||
|
// create the clientset
|
||
|
clientset, err := kubernetes.NewForConfig(config)
|
||
|
if err != nil {
|
||
|
panic(err.Error())
|
||
|
}
|
||
|
|
||
|
var y = ""
|
||
|
fileString := ""
|
||
|
for _, deployment := range deployments {
|
||
|
deploymentObject, err := clientset.AppsV1().Deployments(namespace).Get(deployment, metav1.GetOptions{})
|
||
|
if errors.IsNotFound(err) {
|
||
|
fmt.Printf("Deployment %s in namespace %s not found\n", deployment, namespace)
|
||
|
} else if statusError, isStatus := err.(*errors.StatusError); isStatus {
|
||
|
fmt.Printf("Error getting deployment %s in namespace %s: %v\n",
|
||
|
deployment, namespace, statusError.ErrStatus.Message)
|
||
|
} else if err != nil {
|
||
|
panic(err.Error())
|
||
|
} else {
|
||
|
fmt.Printf("Found deployment %s in namespace %s\n", deployment, namespace)
|
||
|
y = exporters.Deployment(deploymentObject, append(deploymentJqCommands, globalJqCommands...), noBuiltinMods, chart.Name, lessOpinions)
|
||
|
if fileString != "" {
|
||
|
fileString += "---\n"
|
||
|
}
|
||
|
fileString += y
|
||
|
}
|
||
|
}
|
||
|
if y != "" {
|
||
|
err = ioutil.WriteFile("templates/imported-deployment.yaml", []byte(fileString), 0644)
|
||
|
if err != nil {
|
||
|
panic(err.Error())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for _, service := range services {
|
||
|
serviceObject, err := clientset.CoreV1().Services(namespace).Get(service, metav1.GetOptions{})
|
||
|
if errors.IsNotFound(err) {
|
||
|
fmt.Printf("service %s in namespace %s not found\n", service, namespace)
|
||
|
} else if statusError, isStatus := err.(*errors.StatusError); isStatus {
|
||
|
fmt.Printf("Error getting service %s in namespace %s: %v\n",
|
||
|
service, namespace, statusError.ErrStatus.Message)
|
||
|
} else if err != nil {
|
||
|
panic(err.Error())
|
||
|
} else {
|
||
|
fmt.Printf("Found service %s in namespace %s\n", service, namespace)
|
||
|
y = exporters.Service(serviceObject, append(serviceJqCommands, globalJqCommands...), noBuiltinMods, chart.Name, lessOpinions)
|
||
|
if fileString != "" {
|
||
|
fileString += "---\n"
|
||
|
}
|
||
|
fileString += y
|
||
|
}
|
||
|
}
|
||
|
if y != "" {
|
||
|
err = ioutil.WriteFile("templates/imported-service.yaml", []byte(fileString), 0644)
|
||
|
if err != nil {
|
||
|
panic(err.Error())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for _, configmap := range configmaps {
|
||
|
configmapObject, err := clientset.CoreV1().ConfigMaps(namespace).Get(configmap, metav1.GetOptions{})
|
||
|
if errors.IsNotFound(err) {
|
||
|
fmt.Printf("configmap %s in namespace %s not found\n", configmap, namespace)
|
||
|
} else if statusError, isStatus := err.(*errors.StatusError); isStatus {
|
||
|
fmt.Printf("Error getting configmap %s in namespace %s: %v\n",
|
||
|
configmap, namespace, statusError.ErrStatus.Message)
|
||
|
} else if err != nil {
|
||
|
panic(err.Error())
|
||
|
} else {
|
||
|
fmt.Printf("Found configmap %s in namespace %s\n", configmap, namespace)
|
||
|
y = exporters.Configmap(configmapObject, append(serviceJqCommands, globalJqCommands...), noBuiltinMods, chart.Name, lessOpinions)
|
||
|
}
|
||
|
if fileString != "" {
|
||
|
fileString += "---\n"
|
||
|
}
|
||
|
fileString += y
|
||
|
}
|
||
|
if y != "" {
|
||
|
err = ioutil.WriteFile("templates/imported-configmap.yaml", []byte(fileString), 0644)
|
||
|
if err != nil {
|
||
|
panic(err.Error())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for _, secret := range secrets {
|
||
|
secretObject, err := clientset.CoreV1().Secrets(namespace).Get(secret, metav1.GetOptions{})
|
||
|
if errors.IsNotFound(err) {
|
||
|
fmt.Printf("secret %s in namespace %s not found\n", secret, namespace)
|
||
|
} else if statusError, isStatus := err.(*errors.StatusError); isStatus {
|
||
|
fmt.Printf("Error getting secret %s in namespace %s: %v\n",
|
||
|
secret, namespace, statusError.ErrStatus.Message)
|
||
|
} else if err != nil {
|
||
|
panic(err.Error())
|
||
|
} else {
|
||
|
fmt.Printf("Found secret %s in namespace %s\n", secret, namespace)
|
||
|
y = exporters.Secret(secretObject, append(serviceJqCommands, globalJqCommands...), noBuiltinMods, chart.Name, lessOpinions)
|
||
|
}
|
||
|
if fileString != "" {
|
||
|
fileString += "---\n"
|
||
|
}
|
||
|
fileString += y
|
||
|
}
|
||
|
if y != "" {
|
||
|
err = ioutil.WriteFile("templates/imported-secret.yaml", []byte(fileString), 0644)
|
||
|
if err != nil {
|
||
|
panic(err.Error())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for _, ingress := range ingresses {
|
||
|
ingressObject, err := clientset.ExtensionsV1beta1().Ingresses(namespace).Get(ingress, metav1.GetOptions{})
|
||
|
if errors.IsNotFound(err) {
|
||
|
fmt.Printf("ingress %s in namespace %s not found\n", ingress, namespace)
|
||
|
} else if statusError, isStatus := err.(*errors.StatusError); isStatus {
|
||
|
fmt.Printf("Error getting ingress %s in namespace %s: %v\n",
|
||
|
ingress, namespace, statusError.ErrStatus.Message)
|
||
|
} else if err != nil {
|
||
|
panic(err.Error())
|
||
|
} else {
|
||
|
fmt.Printf("Found ingress %s in namespace %s\n", ingress, namespace)
|
||
|
y = exporters.Ingress(ingressObject, append(serviceJqCommands, globalJqCommands...), noBuiltinMods, chart.Name, lessOpinions)
|
||
|
}
|
||
|
if fileString != "" {
|
||
|
fileString += "---\n"
|
||
|
}
|
||
|
fileString += y
|
||
|
}
|
||
|
if y != "" {
|
||
|
err = ioutil.WriteFile("templates/imported-ingress.yaml", []byte(fileString), 0644)
|
||
|
if err != nil {
|
||
|
panic(err.Error())
|
||
|
}
|
||
|
}
|
||
|
}
|