Skip to content

Commit

Permalink
operator-sdk/cmd: add up command
Browse files Browse the repository at this point in the history
  • Loading branch information
fanminshi committed May 4, 2018
1 parent 0b429fb commit 32b397e
Show file tree
Hide file tree
Showing 7 changed files with 147 additions and 12 deletions.
12 changes: 2 additions & 10 deletions commands/operator-sdk/cmd/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,14 @@ package cmd

import (
"fmt"
"io/ioutil"
"os"
"os/exec"

"github.com/operator-framework/operator-sdk/commands/operator-sdk/cmd/cmdutil"
cmdError "github.com/operator-framework/operator-sdk/commands/operator-sdk/error"
"github.com/operator-framework/operator-sdk/pkg/generator"

"github.com/spf13/cobra"
yaml "gopkg.in/yaml.v2"
)

func NewBuildCmd() *cobra.Command {
Expand Down Expand Up @@ -74,14 +73,7 @@ func buildFunc(cmd *cobra.Command, args []string) {
}
fmt.Fprintln(os.Stdout, string(o))

c := &generator.Config{}
fp, err := ioutil.ReadFile(configYaml)
if err != nil {
cmdError.ExitWithError(cmdError.ExitError, fmt.Errorf("failed to read config file %v: (%v)", configYaml, err))
}
if err = yaml.Unmarshal(fp, c); err != nil {
cmdError.ExitWithError(cmdError.ExitError, fmt.Errorf("failed to unmarshal config file %v: (%v)", configYaml, err))
}
c := cmdutil.GetConfig()
if err = generator.RenderOperatorYaml(c, image); err != nil {
cmdError.ExitWithError(cmdError.ExitError, fmt.Errorf("failed to generate deploy/operator.yaml: (%v)", err))
}
Expand Down
37 changes: 37 additions & 0 deletions commands/operator-sdk/cmd/cmdutil/util.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package cmdutil

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

cmdError "github.com/operator-framework/operator-sdk/commands/operator-sdk/error"
"github.com/operator-framework/operator-sdk/pkg/generator"

yaml "gopkg.in/yaml.v2"
)

const configYaml = "./config/config.yaml"

// MustInProjectRoot checks if the current dir is the project root.
func MustInProjectRoot() {
// if the current directory has the "./config/config.yaml" file, then it is safe to say
// we are at the project root.
_, err := os.Stat(configYaml)
if err != nil && os.IsNotExist(err) {
cmdError.ExitWithError(cmdError.ExitError, fmt.Errorf("must in project root dir: %v", err))
}
}

// GetConfig gets the values from ./config/config.yaml and parses them into a Config struct.
func GetConfig() *generator.Config {
c := &generator.Config{}
fp, err := ioutil.ReadFile(configYaml)
if err != nil {
cmdError.ExitWithError(cmdError.ExitError, fmt.Errorf("failed to read config file %v: (%v)", configYaml, err))
}
if err = yaml.Unmarshal(fp, c); err != nil {
cmdError.ExitWithError(cmdError.ExitError, fmt.Errorf("failed to unmarshal config file %v: (%v)", configYaml, err))
}
return c
}
1 change: 1 addition & 0 deletions commands/operator-sdk/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ func NewRootCmd() *cobra.Command {
cmd.AddCommand(NewNewCmd())
cmd.AddCommand(NewBuildCmd())
cmd.AddCommand(NewGenerateCmd())
cmd.AddCommand(NewUpCmd())

return cmd
}
19 changes: 19 additions & 0 deletions commands/operator-sdk/cmd/up.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package cmd

import (
"github.com/operator-framework/operator-sdk/commands/operator-sdk/cmd/up"

"github.com/spf13/cobra"
)

func NewUpCmd() *cobra.Command {
upCmd := &cobra.Command{
Use: "up",
Short: "Launches the operator",
Long: `The up command has subcommands that can launch the operator in various ways.
`,
}

upCmd.AddCommand(up.NewLocalCmd())
return upCmd
}
78 changes: 78 additions & 0 deletions commands/operator-sdk/cmd/up/local.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package up

import (
"fmt"
"os"
"os/exec"
"os/user"
"path/filepath"

"github.com/operator-framework/operator-sdk/commands/operator-sdk/cmd/cmdutil"
cmdError "github.com/operator-framework/operator-sdk/commands/operator-sdk/error"
"github.com/operator-framework/operator-sdk/pkg/util/k8sutil"

"github.com/spf13/cobra"
)

func NewLocalCmd() *cobra.Command {
upLocalCmd := &cobra.Command{
Use: "local",
Short: "Launches the operator locally",
Long: `The operator-sdk up local command launches the operator on the local machine
by building the operator binary with the ability to access a
kubernetes cluster using a kubeconfig file.
`,
Run: upLocalFunc,
}

upLocalCmd.Flags().StringVar(&kubeConfig, "kubeconfig", "", "The file path to kubernetes configuration file; defaults to $HOME/.kube/config")

return upLocalCmd
}

var (
kubeConfig string
)

const (
gocmd = "go"
run = "run"
cmd = "cmd"
main = "main.go"
defaultConfigPath = ".kube/config"
)

func upLocalFunc(cmd *cobra.Command, args []string) {
mustKubeConfig()
cmdutil.MustInProjectRoot()
c := cmdutil.GetConfig()
upLocal(c.ProjectName)
}

// mustKubeConfig checks if the kubeconfig file exists.
func mustKubeConfig() {
// if kubeConfig is not specified, search for the default kubeconfig file under the $HOME/.kube/config.
if len(kubeConfig) == 0 {
usr, err := user.Current()
if err != nil {
cmdError.ExitWithError(cmdError.ExitError, fmt.Errorf("failed to determine user's home dir: %v", err))
}
kubeConfig = filepath.Join(usr.HomeDir, defaultConfigPath)
}

_, err := os.Stat(kubeConfig)
if err != nil && os.IsNotExist(err) {
cmdError.ExitWithError(cmdError.ExitError, fmt.Errorf("failed to find the kubeconfig file (%v): %v", kubeConfig, err))
}
}

func upLocal(projectName string) {
dc := exec.Command(gocmd, run, filepath.Join(cmd, projectName, main))
dc.Stdout = os.Stdout
dc.Stderr = os.Stderr
dc.Env = append(os.Environ(), fmt.Sprintf("%v=%v", k8sutil.KubeConfigEnvVar, kubeConfig))
err := dc.Run()
if err != nil {
cmdError.ExitWithError(cmdError.ExitError, fmt.Errorf("failed to run operator locally: %v", err))
}
}
5 changes: 3 additions & 2 deletions pkg/k8sclient/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"net"
"os"

"github.com/operator-framework/operator-sdk/pkg/util/k8sutil"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
Expand Down Expand Up @@ -89,7 +90,7 @@ func apiResource(gvk schema.GroupVersionKind, restMapper *discovery.DeferredDisc
func mustNewKubeClientAndConfig() (kubernetes.Interface, *rest.Config) {
var cfg *rest.Config
var err error
if os.Getenv("KUBERNETES_CONFIG") != "" {
if os.Getenv(KubeConfigEnvVar) != "" {
cfg, err = outOfClusterConfig()
} else {
cfg, err = inClusterConfig()
Expand Down Expand Up @@ -118,7 +119,7 @@ func inClusterConfig() (*rest.Config, error) {
}

func outOfClusterConfig() (*rest.Config, error) {
kubeconfig := os.Getenv("KUBERNETES_CONFIG")
kubeconfig := os.Getenv(k8sutil.KubeConfigEnvVar)
config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
return config, err
}
7 changes: 7 additions & 0 deletions pkg/util/k8sutil/constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package k8sutil

const (
// KubeConfigEnvVar defines the env variable KUBERNETES_CONFIG which
// contains the kubeconfig file path.
KubeConfigEnvVar = "KUBERNETES_CONFIG"
)

0 comments on commit 32b397e

Please sign in to comment.