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

General clean up #12

Merged
merged 7 commits into from
Jul 1, 2020
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: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ test-cmd-devfile-push:
test-cmd-devfile-deploy:
ginkgo $(GINKGO_FLAGS) -focus="odo devfile deploy command tests" tests/integration/devfile/

# Run odo push devfile command tests
# Run odo deploy delete 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/
Expand Down
27 changes: 14 additions & 13 deletions pkg/devfile/adapters/kubernetes/component/adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,9 @@ func (a Adapter) runBuildConfig(client *occlient.Client, parameters common.Build
if err != nil {
return err
}
log.Successf("Started build %s using BuildConfig", bc.Name)

reader, writer := io.Pipe()
s := log.Spinner("Waiting for build to finish")

var cmdOutput string
// This Go routine will automatically pipe the output from WaitForBuildToFinish to
Expand All @@ -116,6 +116,7 @@ func (a Adapter) runBuildConfig(client *occlient.Client, parameters common.Build
}
}()

s := log.Spinner("Waiting for build to complete")
if err := client.WaitForBuildToFinish(bc.Name, writer); err != nil {
s.End(false)
return errors.Wrapf(err, "unable to build image using BuildConfig %s, error: %s", buildName, cmdOutput)
Expand Down Expand Up @@ -235,8 +236,6 @@ func (a Adapter) Deploy(parameters common.DeployParameters) (err error) {
applicationName := a.ComponentName + "-deploy"
deploymentManifest := &unstructured.Unstructured{}

log.Info("\nDeploying manifest")

// Specify the substitution keys and values
yamlSubstitutions := map[string]string{
"CONTAINER_IMAGE": parameters.Tag,
Expand Down Expand Up @@ -310,22 +309,22 @@ func (a Adapter) Deploy(parameters common.DeployParameters) (err error) {
}
}

s := log.Spinnerf("Deploying the manifest for %s", gvk.Kind)
actionType := "Creating"
if instanceFound {
actionType = "Updating" // Update deployment
}
s := log.Spinnerf("%s resource of kind %s", strings.Title(actionType), gvk.Kind)
result := &unstructured.Unstructured{}
actionType := "create"
if !instanceFound {
result, err = a.Client.DynamicClient.Resource(gvr).Namespace(namespace).Create(deploymentManifest, metav1.CreateOptions{})
} else {
actionType = "update" // Update deployment
result, err = a.Client.DynamicClient.Resource(gvr).Namespace(namespace).Update(deploymentManifest, metav1.UpdateOptions{})
}
if err != nil {
s.End(false)
return errors.Wrapf(err, "Failed to %s manifest %s", actionType, gvk.Kind)
} else {
s.End(true)
log.Successf("%sd manifest for %s (%s)", strings.Title(actionType), applicationName, gvk.Kind)
return errors.Wrapf(err, "Failed when %s manifest %s", actionType, gvk.Kind)
}
s.End(true)

// Write the returned manifest to the local manifest file
if writtenToManifest {
Expand Down Expand Up @@ -369,16 +368,18 @@ func (a Adapter) Deploy(parameters common.DeployParameters) (err error) {
knGvr := schema.GroupVersionResource{Group: "serving.knative.dev", Version: "v1", Resource: "routes"}
route, err := a.waitForManifestDeployCompletion(applicationName, knGvr, "Ready")
if err != nil {
s.End(false)
return errors.Wrap(err, "error while waiting for deployment completion")
}
fullURL = route.UnstructuredContent()["status"].(map[string]interface{})["url"].(string)
}
s.End(true)

if fullURL != "" {
log.Successf("URL for application %s: %s", applicationName, fullURL)
s.End(true)
log.Successf("Successfully deployed component: %s", fullURL)
} else {
log.Errorf("URL unable to be determined for application %s", applicationName)
s.End(false)
log.Errorf("URL unable to be determined for component %s", a.ComponentName)
}

return nil
Expand Down
9 changes: 0 additions & 9 deletions pkg/devfile/parser/data/common/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,15 +100,6 @@ type DevfileComponent struct {

// Volume component
Volume *Volume `json:"volume,omitempty"`

// Dockerfile component
Dockerfile *Dockerfile `json:"dockerfile,omitempty"`
}

// Dockerfile cmponent
type Dockerfile struct {
Path string `json:"path"`
Args []string `json:"args,omitempty"`
}

// DevfileProject project defined in devfile
Expand Down
83 changes: 47 additions & 36 deletions pkg/odo/cli/component/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package component

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

devfileParser "github.com/openshift/odo/pkg/devfile/parser"
Expand All @@ -11,7 +10,6 @@ import (
projectCmd "github.com/openshift/odo/pkg/odo/cli/project"
"github.com/openshift/odo/pkg/odo/genericclioptions"
"github.com/openshift/odo/pkg/odo/util/completion"
"github.com/openshift/odo/pkg/odo/util/experimental"
"github.com/openshift/odo/pkg/util"
"github.com/pkg/errors"
"github.com/spf13/cobra"
Expand All @@ -21,39 +19,52 @@ import (
ktemplates "k8s.io/kubectl/pkg/util/templates"
)

// TODO: add CLI Reference doc
// TODO: add delete example
var deployCmdExample = ktemplates.Examples(` # Deploys an image and deploys the application
var deployCmdExample = ktemplates.Examples(` # Build and Deploy the current component
%[1]s

# Specify the tag for the image by calling
%[1]s --tag <registry>/<namespace>/<image>:<tag>
`)

// DeployRecommendedCommandName is the recommended build command name
const DeployRecommendedCommandName = "deploy"

// DeployOptions encapsulates options that build command uses
type DeployOptions struct {
*CommonPushOptions
componentContext string
sourcePath string
ignores []string
EnvSpecificInfo *envinfo.EnvSpecificInfo

// devfile path
DevfilePath string
devObj devfileParser.DevfileObj
DockerfileURL string
DockerfileBytes []byte
namespace string
tag string
ManifestSource []byte

*genericclioptions.Context
}

// NewDeployOptions returns new instance of BuildOptions
// with "default" values for certain values, for example, show is "false"
func NewDeployOptions() *DeployOptions {
return &DeployOptions{
CommonPushOptions: NewCommonPushOptions(),
return &DeployOptions{}
}

// CompleteDevfilePath completes the devfile path from context
func (do *DeployOptions) CompleteDevfilePath() {
if len(do.DevfilePath) > 0 {
do.DevfilePath = filepath.Join(do.componentContext, do.DevfilePath)
} else {
do.DevfilePath = filepath.Join(do.componentContext, "devfile.yaml")
}
}

// Complete completes push args
// Complete completes deploy args
func (do *DeployOptions) Complete(name string, cmd *cobra.Command, args []string) (err error) {
do.DevfilePath = filepath.Join(do.componentContext, do.DevfilePath)
do.CompleteDevfilePath()
envInfo, err := envinfo.NewEnvSpecificInfo(do.componentContext)
if err != nil {
return errors.Wrap(err, "unable to retrieve configuration information")
Expand All @@ -67,49 +78,42 @@ func (do *DeployOptions) Complete(name string, cmd *cobra.Command, args []string
// Validate validates the push parameters
func (do *DeployOptions) Validate() (err error) {

log.Infof("\nValidation")
// Validate the --tag
if do.tag == "" {
return errors.New("odo deploy requires a tag, in the format <registry>/namespace>/<image>")
}

s := log.Spinner("Validating arguments")
err = util.ValidateTag(do.tag)
if err != nil {
s.End(false)
return err
}
s.End(true)

return
}

// Run has the logic to perform the required actions as part of command
func (do *DeployOptions) Run() (err error) {
devObj, err := devfileParser.Parse(do.DevfilePath)
do.devObj, err = devfileParser.Parse(do.DevfilePath)
if err != nil {
return err
}

metadata := devObj.Data.GetMetadata()
s = log.Spinner("Validating build information")
metadata := do.devObj.Data.GetMetadata()
dockerfileURL := metadata.Dockerfile
localDir, err := os.Getwd()
if err != nil {
return err
}

//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.
if dockerfileURL != "" && util.CheckPathExists(filepath.Join(localDir, "Dockerfile")) {
if dockerfileURL != "" && util.CheckPathExists(filepath.Join(do.componentContext, "Dockerfile")) {
// TODO: make clearer more visible output
log.Warning("Dockerfile already exists in project directory and one is specified in Devfile.")
log.Warningf("Using Dockerfile specified in devfile from '%s'", dockerfileURL)
}

if !util.CheckPathExists(filepath.Join(localDir, ".odo")) {
return errors.Wrap(err, ".odo folder not found")
}

if dockerfileURL != "" {
dockerfileBytes, err := util.DownloadFileInMemory(dockerfileURL)
if err != nil {
s.End(false)
return errors.New("unable to download Dockerfile from URL specified in devfile")
}
// If we successfully downloaded the Dockerfile into memory, store it in the DeployOptions
Expand All @@ -118,33 +122,42 @@ func (do *DeployOptions) Run() (err error) {
// Validate the file that was downloaded is a Dockerfile
err = util.ValidateDockerfile(dockerfileBytes)
if err != nil {
s.End(false)
return err
}

} else if !util.CheckPathExists(filepath.Join(localDir, "Dockerfile")) {
} else if !util.CheckPathExists(filepath.Join(do.componentContext, "Dockerfile")) {
s.End(false)
return errors.New("dockerfile required for build. No 'dockerfile' field found in devfile, or Dockerfile found in project directory")
}

err = do.DevfileBuild()
if err != nil {
return err
}
s.End(true)

s = log.Spinner("Validating deployment information")
manifestURL := metadata.Manifest
if manifestURL == "" {
s.End(false)
return errors.New("Unable to deploy as alpha.deployment-manifest is not defined in devfile.yaml")
}

err = util.ValidateURL(manifestURL)
if err != nil {
s.End(false)
return errors.New(fmt.Sprintf("Invalid manifest url: %s, %s", manifestURL, err))
}

do.ManifestSource, err = util.DownloadFileInMemory(manifestURL)
if err != nil {
s.End(false)
return errors.New(fmt.Sprintf("Unable to download manifest: %s, %s", manifestURL, err))
}
s.End(true)

return
}

// Run has the logic to perform the required actions as part of command
func (do *DeployOptions) Run() (err error) {
err = do.DevfileDeploy()
if err != nil {
return err
Expand Down Expand Up @@ -178,10 +191,8 @@ func NewCmdDeploy(name, fullName string) *cobra.Command {
genericclioptions.AddContextFlag(deployCmd, &do.componentContext)

// enable devfile flag if experimental mode is enabled
if experimental.IsExperimentalModeEnabled() {
deployCmd.Flags().StringVar(&do.DevfilePath, "devfile", "./devfile.yaml", "Path to a devfile.yaml")
deployCmd.Flags().StringVar(&do.tag, "tag", "", "Tag used to build the image")
}
deployCmd.Flags().StringVar(&do.tag, "tag", "", "Tag used to build the image")
deployCmd.Flags().StringSliceVar(&do.ignores, "ignore", []string{}, "Files or folders to be ignored via glob expressions.")

//Adding `--project` flag
projectCmd.AddProjectFlag(deployCmd)
Expand Down
Loading