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

Delete deploy #7

Merged
merged 5 commits into from
Jun 25, 2020
Merged
Show file tree
Hide file tree
Changes from 4 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
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,11 @@ test-cmd-devfile-create:
test-cmd-devfile-push:
ginkgo $(GINKGO_FLAGS) -focus="odo devfile push command tests" tests/integration/devfile/

# Run odo push devfile command tests
.PHONY: test-cmd-devfile-deploy-delete
test-cmd-devfile-deploy-delete:
ginkgo $(GINKGO_FLAGS) -focus="odo devfile deploy delete command tests" tests/integration/devfile/

# Run odo devfile watch command tests
.PHONY: test-cmd-devfile-watch
test-cmd-devfile-watch:
Expand Down
1 change: 1 addition & 0 deletions pkg/devfile/adapters/common/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ type ComponentAdapter interface {
Deploy(parameters DeployParameters) error
DoesComponentExist(cmpName string) bool
Delete(labels map[string]string) error
DeployDelete(manifest []byte) error
}

// StorageAdapter defines the storage functions that platform-specific adapters must implement
Expand Down
8 changes: 7 additions & 1 deletion pkg/devfile/adapters/docker/adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,18 @@ func (d Adapter) Push(parameters common.PushParameters) error {
return nil
}

func (k Adapter) Build(parameters common.BuildParameters) error { return nil }
func (k Adapter) Build(parameters common.BuildParameters) error {
return errors.New("Deploy command not supported when building image using pushTarget=Docker")
}

func (k Adapter) Deploy(parameters common.DeployParameters) error {
return errors.New("Deploy command not supported when using pushTarget=Docker")
}

func (k Adapter) DeployDelete(manifest []byte) error {
return errors.New("Deploy delete command not supported when using pushTarget=Docker")
}

// DoesComponentExist returns true if a component with the specified name exists
func (d Adapter) DoesComponentExist(cmpName string) bool {
return d.componentAdapter.DoesComponentExist(cmpName)
Expand Down
2 changes: 2 additions & 0 deletions pkg/devfile/adapters/docker/component/adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ func (a Adapter) Build(parameters common.BuildParameters) (err error) { return n

func (a Adapter) Deploy(parameters common.DeployParameters) (err error) { return nil }

func (a Adapter) DeployDelete(manifest []byte) (err error) { return nil }

// Push updates the component if a matching component exists or creates one if it doesn't exist
func (a Adapter) Push(parameters common.PushParameters) (err error) {
componentExists := utils.ComponentExists(a.Client, a.ComponentName)
Expand Down
1 change: 1 addition & 0 deletions pkg/devfile/adapters/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ type PlatformAdapter interface {
Deploy(parameters common.DeployParameters) error
DoesComponentExist(cmpName string) bool
Delete(labels map[string]string) error
DeployDelete(manifest []byte) error
}
11 changes: 11 additions & 0 deletions pkg/devfile/adapters/kubernetes/adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,17 @@ func (k Adapter) Deploy(parameters common.DeployParameters) error {
return nil
}

// Build creates Kubernetes resources to build an image for the component
func (k Adapter) DeployDelete(manifest []byte) error {

err := k.componentAdapter.DeployDelete(manifest)
if err != nil {
return errors.Wrap(err, "Failed to delete the deployed application")
}

return nil
}

func (k Adapter) DoesComponentExist(cmpName string) bool {
return k.componentAdapter.DoesComponentExist(cmpName)
}
Expand Down
85 changes: 77 additions & 8 deletions pkg/devfile/adapters/kubernetes/component/adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"fmt"
"os"
"path/filepath"
"reflect"
"strconv"
"strings"
Expand Down Expand Up @@ -190,7 +191,7 @@ func (a Adapter) Build(parameters common.BuildParameters) (err error) {
}

// Need to wait for container to start
time.Sleep(5 * time.Second)
time.Sleep(10 * time.Second)

// Sync files to volume
log.Infof("\nSyncing to component %s", a.ComponentName)
Expand All @@ -215,10 +216,10 @@ func (a Adapter) Build(parameters common.BuildParameters) (err error) {
return
}

func determinePort(parameters common.DeployParameters) string {
func determinePort(envSpecificInfo envinfo.EnvSpecificInfo) string {
// TODO: Determine port to use (from env.yaml or other location!!)
deploymentPort := ""
for _, localURL := range parameters.EnvSpecificInfo.GetURL() {
for _, localURL := range envSpecificInfo.GetURL() {
if localURL.Kind != envinfo.DOCKER {
deploymentPort = strconv.Itoa(localURL.Port)
break
Expand All @@ -241,7 +242,6 @@ func substitueYamlVariables(baseYaml []byte, yamlSubstitutions map[string]string

// Build image for devfile project
func (a Adapter) Deploy(parameters common.DeployParameters) (err error) {

namespace := a.Client.Namespace
applicationName := a.ComponentName + "-deploy"
deploymentManifest := &unstructured.Unstructured{}
Expand All @@ -252,30 +252,50 @@ func (a Adapter) Deploy(parameters common.DeployParameters) (err error) {

// Specify the substitution keys and values
yamlSubstitutions := map[string]string{
// TODO: this tag is not passed to delete, do we need to template
"CONTAINER_IMAGE": parameters.Tag,
"PROJECT_NAME": applicationName,
"PORT": determinePort(parameters),
"PORT": determinePort(parameters.EnvSpecificInfo),
}

// Substitute the values in the manifest file
deployYaml := substitueYamlVariables(parameters.ManifestSource, yamlSubstitutions)
klog.V(3).Infof("Deploy manifest:\n\n%s", string(deployYaml))

// Build a yaml decoder with the unstructured Scheme
yamlDecoder := yaml.NewDecodingSerializer(unstructured.UnstructuredJSONScheme)

_, gvk, err := yamlDecoder.Decode([]byte(deployYaml), nil, deploymentManifest)
if err != nil {
return err
}

klog.V(3).Infof("Deploy manifest:\n\n%s", deploymentManifest)
gvr := schema.GroupVersionResource{Group: gvk.Group, Version: gvk.Version, Resource: strings.ToLower(gvk.Kind + "s")}
klog.V(3).Infof("Manifest type: %s", gvr.String())

labels := map[string]string{
"component": applicationName,
}

manifestLabels := deploymentManifest.GetLabels()
if manifestLabels != nil {
for key, value := range labels {
manifestLabels[key] = value
}
deploymentManifest.SetLabels(manifestLabels)
} else {
deploymentManifest.SetLabels(labels)
}

// TODO: Determine why using a.Client.DynamicClient doesnt work
// Need to create my own client in order to get the dynamic parts working
myclient, err := dynamic.NewForConfig(a.Client.KubeClientConfig)
if err != nil {
panic(err)
return err
}

// Check to see whether deployed resource already exists. If not, create else update
// Get?
instanceFound := false
list, err := myclient.Resource(gvr).Namespace(namespace).List(metav1.ListOptions{})
if list != nil && len(list.Items) > 0 {
Expand Down Expand Up @@ -308,7 +328,56 @@ func (a Adapter) Deploy(parameters common.DeployParameters) (err error) {
s.End(true)
log.Infof("Deployed %s %s.\n", gvk.Kind, result.GetName())

return
// This will override if manifest.yaml is present
manifestFile, err := os.Create(filepath.Join(a.Context, ".odo", "manifest.yaml"))
if err != nil {
err = manifestFile.Close()
return err
}
err = yamlDecoder.Encode(result, manifestFile)

if err != nil {
err = manifestFile.Close()
return err
}

err = manifestFile.Close()
return err
}

func (a Adapter) DeployDelete(manifest []byte) (err error) {
deploymentManifest := &unstructured.Unstructured{}
// Build a yaml decoder with the unstructured Scheme
yamlDecoder := yaml.NewDecodingSerializer(unstructured.UnstructuredJSONScheme)
manifests := bytes.Split(manifest, []byte("---"))
for _, splitManifest := range manifests {
if len(manifest) > 0 {
_, gvk, err := yamlDecoder.Decode([]byte(splitManifest), nil, deploymentManifest)
if err != nil {
return err
}
klog.V(3).Infof("Deploy manifest:\n\n%s", deploymentManifest)
gvr := schema.GroupVersionResource{Group: gvk.Group, Version: gvk.Version, Resource: strings.ToLower(gvk.Kind + "s")}
klog.V(3).Infof("Manifest type: %s", gvr.String())
// TODO: Determine why using a.Client.DynamicClient doesnt work
// Need to create my own client in order to get the dynamic parts working
myclient, err := dynamic.NewForConfig(a.Client.KubeClientConfig)
if err != nil {
return err
}
// TODO: Check if resource is running in the cluster before attempting to delete Warning
_, err = myclient.Resource(gvr).Namespace(a.Client.Namespace).Get(deploymentManifest.GetName(), metav1.GetOptions{})
if err != nil {
errorMessage := "Could not delete deployment " + deploymentManifest.GetName() + " as deployment was not found"
return errors.New(errorMessage)
}
err = myclient.Resource(gvr).Namespace(a.Client.Namespace).Delete(deploymentManifest.GetName(), &metav1.DeleteOptions{})
if err != nil {
return err
}
}
}
return nil
}

// Push updates the component if a matching component exists or creates one if it doesn't exist
Expand Down
3 changes: 2 additions & 1 deletion pkg/odo/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,6 @@ func odoRootCmd(name, fullName string) *cobra.Command {
component.NewCmdComponent(component.RecommendedCommandName, util.GetFullName(fullName, component.RecommendedCommandName)),
component.NewCmdCreate(component.CreateRecommendedCommandName, util.GetFullName(fullName, component.CreateRecommendedCommandName)),
component.NewCmdDelete(component.DeleteRecommendedCommandName, util.GetFullName(fullName, component.DeleteRecommendedCommandName)),
component.NewCmdDeploy(component.DeployRecommendedCommandName, util.GetFullName(fullName, component.DeployRecommendedCommandName)),
component.NewCmdDescribe(component.DescribeRecommendedCommandName, util.GetFullName(fullName, component.DescribeRecommendedCommandName)),
component.NewCmdLink(component.LinkRecommendedCommandName, util.GetFullName(fullName, component.LinkRecommendedCommandName)),
component.NewCmdUnlink(component.UnlinkRecommendedCommandName, util.GetFullName(fullName, component.UnlinkRecommendedCommandName)),
Expand All @@ -203,6 +202,7 @@ func odoRootCmd(name, fullName string) *cobra.Command {
if experimental.IsExperimentalModeEnabled() {
rootCmd.AddCommand(
registry.NewCmdRegistry(registry.RecommendedCommandName, util.GetFullName(fullName, registry.RecommendedCommandName)),
component.NewCmdDeploy(component.DeployRecommendedCommandName, util.GetFullName(fullName, component.DeployRecommendedCommandName)),
)
}

Expand All @@ -222,6 +222,7 @@ func reconfigureCmdWithSubcmd(cmd *cobra.Command) {
if cmd.Args == nil {
cmd.Args = cobra.ArbitraryArgs
}

if cmd.RunE == nil {
cmd.RunE = ShowSubcommands
}
Expand Down
3 changes: 2 additions & 1 deletion pkg/odo/cli/component/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ func NewCmdComponent(name, fullName string) *cobra.Command {
pushCmd := NewCmdPush(PushRecommendedCommandName, odoutil.GetFullName(fullName, PushRecommendedCommandName))
updateCmd := NewCmdUpdate(UpdateRecommendedCommandName, odoutil.GetFullName(fullName, UpdateRecommendedCommandName))
watchCmd := NewCmdWatch(WatchRecommendedCommandName, odoutil.GetFullName(fullName, WatchRecommendedCommandName))
deployDeleteCmd := NewCmdDeployDelete(DeployDeleteRecommendedCommandName, odoutil.GetFullName(fullName, DeployDeleteRecommendedCommandName))
EnriqueL8 marked this conversation as resolved.
Show resolved Hide resolved

// componentCmd represents the component command
var componentCmd = &cobra.Command{
Expand All @@ -70,7 +71,7 @@ func NewCmdComponent(name, fullName string) *cobra.Command {
// add flags from 'get' to component command
componentCmd.Flags().AddFlagSet(componentGetCmd.Flags())

componentCmd.AddCommand(componentGetCmd, createCmd, deleteCmd, describeCmd, deployCmd, linkCmd, unlinkCmd, listCmd, logCmd, pushCmd, updateCmd, watchCmd)
componentCmd.AddCommand(componentGetCmd, createCmd, deleteCmd, deployDeleteCmd, describeCmd, deployCmd, linkCmd, unlinkCmd, listCmd, logCmd, pushCmd, updateCmd, watchCmd)
EnriqueL8 marked this conversation as resolved.
Show resolved Hide resolved

// Add a defined annotation in order to appear in the help menu
componentCmd.Annotations = map[string]string{"command": "main"}
Expand Down
33 changes: 23 additions & 10 deletions pkg/odo/cli/component/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
)

// TODO: add CLI Reference doc
// TODO: add delete example
var deployCmdExample = ktemplates.Examples(` # Deploys an image and deploys the application
%[1]s
`)
Expand Down Expand Up @@ -52,6 +53,7 @@ func NewDeployOptions() *DeployOptions {

// Complete completes push args
func (do *DeployOptions) Complete(name string, cmd *cobra.Command, args []string) (err error) {
fmt.Println("%%%%%% in deploy complete &&&&")
do.DevfilePath = filepath.Join(do.componentContext, do.DevfilePath)
envInfo, err := envinfo.NewEnvSpecificInfo(do.componentContext)
if err != nil {
Expand Down Expand Up @@ -85,19 +87,14 @@ func (do *DeployOptions) Run() (err error) {
if err != nil {
return err
}

metadata := devObj.Data.GetMetadata()
dockerfileURL := metadata.Dockerfile
localDir, err := os.Getwd()
if err != nil {
return err
}

manifestURL := metadata.Manifest
do.ManifestSource, err = util.DownloadFileInMemory(manifestURL)
if err != nil {
return errors.Wrap(err, "Unable to download manifest "+manifestURL)
}

//Download Dockerfile to .odo, build, then delete from .odo dir
//If Dockerfile is present in the project already, use that for the build
//If Dockerfile is present in the project and field is in devfile, build the one already in the project and warn the user.
Expand Down Expand Up @@ -134,6 +131,12 @@ func (do *DeployOptions) Run() (err error) {
return err
}

manifestURL := metadata.Manifest
do.ManifestSource, err = util.DownloadFileInMemory(manifestURL)
if err != nil {
return errors.Wrap(err, "Unable to download manifest "+manifestURL)
}

err = do.DevfileDeploy()
if err != nil {
return err
Expand All @@ -142,20 +145,27 @@ func (do *DeployOptions) Run() (err error) {
return nil
}

// Need to use RunE on Cobra command to allow for `odo deploy` and `odo deploy delete`
// See reconfigureCmdWithSubCmd function in cli.go
func (do *DeployOptions) deployRunE(cmd *cobra.Command, args []string) error {
genericclioptions.GenericRun(do, cmd, args)
return nil
}

// NewCmdDeploy implements the push odo command
func NewCmdDeploy(name, fullName string) *cobra.Command {
do := NewDeployOptions()

deployDeleteCmd := NewCmdDeployDelete(DeployDeleteRecommendedCommandName, odoutil.GetFullName(fullName, DeployDeleteRecommendedCommandName))

var deployCmd = &cobra.Command{
Use: fmt.Sprintf("%s [component name]", name),
Use: fmt.Sprintf("%s [command] [component name]", name),
Short: "Deploy image for component",
Long: `Deploy image for component`,
Example: fmt.Sprintf(deployCmdExample, fullName),
Args: cobra.MaximumNArgs(1),
Annotations: map[string]string{"command": "component"},
Run: func(cmd *cobra.Command, args []string) {
genericclioptions.GenericRun(do, cmd, args)
},
RunE: do.deployRunE,
}
genericclioptions.AddContextFlag(deployCmd, &do.componentContext)

Expand All @@ -168,6 +178,9 @@ func NewCmdDeploy(name, fullName string) *cobra.Command {
//Adding `--project` flag
projectCmd.AddProjectFlag(deployCmd)

//fmt.Println("$$$$$", DeployDeleteRecommendedCommandName, "$$$$$$")
deployCmd.AddCommand(deployDeleteCmd)
//fmt.Println("$$$$$", deployCmd.Commands()[0], "$$$$$$")
EnriqueL8 marked this conversation as resolved.
Show resolved Hide resolved
deployCmd.SetUsageTemplate(odoutil.CmdUsageTemplate)
completion.RegisterCommandHandler(deployCmd, completion.ComponentNameCompletionHandler)
completion.RegisterCommandFlagHandler(deployCmd, "context", completion.FileCompletionHandler)
Expand Down
Loading