Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple enhancements #3

Merged
merged 1 commit into from
Jan 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions api/holodeck/v1alpha1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ const (
ContainerRuntimeContainerd ContainerRuntimeName = "containerd"
// ContainerRuntimeCrio means the container runtime is Crio
ContainerRuntimeCrio ContainerRuntimeName = "crio"
// ContainerRuntimeNone means the container runtime is not defined
ContainerRuntimeNone ContainerRuntimeName = ""
)

type Kubernetes struct {
Expand Down
63 changes: 36 additions & 27 deletions cmd/create/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ import (
"path/filepath"

"github.com/NVIDIA/holodeck/api/holodeck/v1alpha1"
"github.com/NVIDIA/holodeck/internal/logger"
"github.com/NVIDIA/holodeck/pkg/jyaml"
"github.com/NVIDIA/holodeck/pkg/provider/aws"
"github.com/NVIDIA/holodeck/pkg/provisioner"

"github.com/sirupsen/logrus"
cli "github.com/urfave/cli/v2"
)

Expand All @@ -44,13 +44,13 @@ type options struct {
}

type command struct {
logger *logrus.Logger
log *logger.FunLogger
}

// NewCommand constructs the create command with the specified logger
func NewCommand(logger *logrus.Logger) *cli.Command {
func NewCommand(log *logger.FunLogger) *cli.Command {
c := command{
logger: logger,
log: log,
}
return c.build()
}
Expand Down Expand Up @@ -93,8 +93,7 @@ func (m command) build() *cli.Command {
var err error
opts.cfg, err = jyaml.UnmarshalFromFile[v1alpha1.Environment](opts.envFile)
if err != nil {
fmt.Printf("failed to read config file: %v\n", err)
return err
return fmt.Errorf("error reading config file: %s", err)
}

// set cache path
Expand All @@ -103,6 +102,11 @@ func (m command) build() *cli.Command {
}
opts.cachefile = filepath.Join(opts.cachePath, opts.cfg.Name+".yaml")

// if no containerruntime is specified, default to none
if opts.cfg.Spec.ContainerRuntime.Name == "" {
opts.cfg.Spec.ContainerRuntime.Name = v1alpha1.ContainerRuntimeNone
}

return nil
},
Action: func(c *cli.Context) error {
Expand All @@ -115,7 +119,7 @@ func (m command) build() *cli.Command {

func (m command) run(c *cli.Context, opts *options) error {
if opts.cfg.Spec.Provider == v1alpha1.ProviderAWS {
err := createAWS(opts)
err := createAWS(m.log, opts)
if err != nil {
return fmt.Errorf("failed to create AWS infra: %v", err)
}
Expand All @@ -125,11 +129,12 @@ func (m command) run(c *cli.Context, opts *options) error {
return fmt.Errorf("failed to read cache file: %v", err)
}
} else if opts.cfg.Spec.Provider == v1alpha1.ProviderSSH {
m.log.Info("SSH infrastructure \u2601")
opts.cache = opts.cfg
}

if opts.provision {
err := runProvision(opts)
err := runProvision(m.log, opts)
if err != nil {
return fmt.Errorf("failed to provision: %v", err)
}
Expand All @@ -138,8 +143,11 @@ func (m command) run(c *cli.Context, opts *options) error {
return nil
}

func runProvision(opts *options) error {
func runProvision(log *logger.FunLogger, opts *options) error {
var hostUrl string

log.Info("Provisioning \u2699")

if opts.cfg.Spec.Provider == v1alpha1.ProviderAWS {
for _, p := range opts.cache.Status.Properties {
if p.Name == aws.PublicDnsName {
Expand All @@ -151,7 +159,7 @@ func runProvision(opts *options) error {
hostUrl = opts.cfg.Spec.Instance.HostUrl
}

p, err := provisioner.New(opts.cfg.Spec.Auth.PrivateKey, hostUrl)
p, err := provisioner.New(log, opts.cfg.Spec.Auth.PrivateKey, hostUrl)
if err != nil {
return err
}
Expand All @@ -161,8 +169,13 @@ func runProvision(opts *options) error {
}

// Download kubeconfig
if opts.cfg.Spec.Kubernetes.Install {
if err = getKubeConfig(opts, p); err != nil {
if opts.cfg.Spec.Kubernetes.Install && opts.cfg.Spec.Kubernetes.KubeConfig != "" {
if opts.cfg.Spec.Kubernetes.KubernetesInstaller == "microk8s" || opts.cfg.Spec.Kubernetes.KubernetesInstaller == "kind" {
log.Warning("kubeconfig is not supported for %s, skipping kubeconfig download", opts.cfg.Spec.Kubernetes.KubernetesInstaller)
return nil
}

if err = getKubeConfig(log, opts, p); err != nil {
return fmt.Errorf("failed to get kubeconfig: %v", err)
}
}
Expand All @@ -171,12 +184,12 @@ func runProvision(opts *options) error {
}

// getKubeConfig downloads the kubeconfig file from the remote host
func getKubeConfig(opts *options, p *provisioner.Provisioner) error {
func getKubeConfig(log *logger.FunLogger, opts *options, p *provisioner.Provisioner) error {
remoteFilePath := "/home/ubuntu/.kube/config"
if opts.cfg.Spec.Kubernetes.KubeConfig == "" {
// and
if opts.kubeconfig == "" {
fmt.Printf("kubeconfig is not set, use default kubeconfig path: %s\n", filepath.Join(opts.cachePath, "kubeconfig"))
log.Warning("kubeconfig is not set, use default kubeconfig path: %s\n", filepath.Join(opts.cachePath, "kubeconfig"))
// if kubeconfig is not set, use set to current directory as default
// first get current directory
pwd := os.Getenv("PWD")
Expand All @@ -189,23 +202,20 @@ func getKubeConfig(opts *options, p *provisioner.Provisioner) error {
// Create a session
session, err := p.Client.NewSession()
if err != nil {
fmt.Printf("Failed to create session: %v\n", err)
return err
return fmt.Errorf("error creating session: %v", err)
}
defer session.Close()

// Set up a pipe to receive the remote file content
remoteFile, err := session.StdoutPipe()
if err != nil {
fmt.Printf("Error obtaining remote file pipe: %v\n", err)
return err
return fmt.Errorf("error creating remote file pipe: %v", err)
}

// Start the remote command to read the file content
err = session.Start(fmt.Sprintf("/usr/bin/cat %s", remoteFilePath))
if err != nil {
fmt.Printf("Error starting remote command: %v\n", err)
return err
return fmt.Errorf("error starting remote command: %v", err)
}

// Create a new file on the local system to save the downloaded content
Expand All @@ -218,24 +228,23 @@ func getKubeConfig(opts *options, p *provisioner.Provisioner) error {
// Copy the remote file content to the local file
_, err = io.Copy(localFile, remoteFile)
if err != nil {
fmt.Printf("Error copying file content: %v\n", err)
return err
return fmt.Errorf("error copying remote file to local: %v", err)
}

// Wait for the remote command to finish
err = session.Wait()
if err != nil {
fmt.Printf("Error waiting for remote command: %v\n", err)
return err
return fmt.Errorf("error waiting for remote command: %v", err)
}

fmt.Printf("Kubeconfig saved to %s\n", opts.kubeconfig)
log.Info(fmt.Sprintf("Kubeconfig saved to %s\n", opts.kubeconfig))

return nil
}

func createAWS(opts *options) error {
client, err := aws.New(opts.cfg, opts.cachefile)
func createAWS(log *logger.FunLogger, opts *options) error {
log.Info("Creating AWS infrastructure \u2601")
client, err := aws.New(log, opts.cfg, opts.cachefile)
if err != nil {
return err
}
Expand Down
33 changes: 15 additions & 18 deletions cmd/delete/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ import (
"path/filepath"

"github.com/NVIDIA/holodeck/api/holodeck/v1alpha1"
"github.com/NVIDIA/holodeck/internal/logger"
"github.com/NVIDIA/holodeck/pkg/jyaml"
"github.com/NVIDIA/holodeck/pkg/provider/aws"

"github.com/sirupsen/logrus"
cli "github.com/urfave/cli/v2"
)

Expand All @@ -40,13 +40,13 @@ type options struct {
}

type command struct {
logger *logrus.Logger
log *logger.FunLogger
}

// NewCommand constructs the delete command with the specified logger
func NewCommand(logger *logrus.Logger) *cli.Command {
func NewCommand(log *logger.FunLogger) *cli.Command {
c := command{
logger: logger,
log: log,
}
return c.build()
}
Expand Down Expand Up @@ -77,13 +77,11 @@ func (m command) build() *cli.Command {
var err error
opts.cfg, err = jyaml.UnmarshalFromFile[v1alpha1.Environment](opts.envFile)
if err != nil {
fmt.Printf("Error reading config file: %s\n", err)
return err
return fmt.Errorf("error reading config file: %s", err)
}

if opts.cfg.Spec.Provider != v1alpha1.ProviderAWS {
fmt.Printf("Only AWS provider is supported\n")
return err
return fmt.Errorf("provider %s not supported", opts.cfg.Spec.Provider)
}

// read hostUrl from cache
Expand Down Expand Up @@ -113,15 +111,15 @@ func (m command) run(c *cli.Context, opts *options) error {

cfg, err := jyaml.UnmarshalFromFile[v1alpha1.Environment](opts.envFile)
if err != nil {
fmt.Printf("Error reading config file: %s\n", err)
os.Exit(1)
m.log.Error(err)
m.log.Exit(1)
}
cachefile := filepath.Join(opts.cachePath, cfg.Name+".yaml")

client, err := aws.New(cfg, cachefile)
client, err := aws.New(m.log, cfg, cachefile)
if err != nil {
fmt.Printf("Error creating client: %s\n", err)
os.Exit(1)
m.log.Error(err)
m.log.Exit(1)
}

// check if cache exists
Expand All @@ -131,13 +129,12 @@ func (m command) run(c *cli.Context, opts *options) error {
os.Exit(1)
}

err = client.Delete()
if err != nil {
fmt.Printf("Error deleting environment: %s\n", err)
os.Exit(1)
if err := client.Delete(); err != nil {
m.log.Error(err)
m.log.Exit(1)
}

fmt.Printf("Successfully deleted environment %s\n", cfg.Name)
m.log.Info("Successfully deleted environment %s\n", cfg.Name)

return nil
}
Loading