Removes the s2i flag from the create file (#5023)

This commit is contained in:
Mrinal Das
2021-09-21 18:48:39 +05:30
committed by GitHub
parent 75f1be61db
commit 74fc779a4a
39 changed files with 399 additions and 4158 deletions

View File

@@ -171,34 +171,14 @@ test-cmd-login-logout: ## Run odo login and logout tests
test-cmd-link-unlink-4-cluster: ## Run link and unlink commnad tests against 4.x cluster
$(RUN_GINKGO) $(GINKGO_FLAGS) -focus="odo link and unlink commnad tests" tests/integration/
.PHONY: test-cmd-service
test-cmd-service: ## Run odo service command tests
$(RUN_GINKGO) $(GINKGO_FLAGS) -focus="odo service command tests" tests/integration/servicecatalog/
.PHONY: test-cmd-project
test-cmd-project: ## Run odo project command tests
$(RUN_GINKGO) $(GINKGO_FLAGS) -focus="odo project command tests" tests/integration/project/
.PHONY: test-cmd-app
test-cmd-app: ## Run odo app command tests
$(RUN_GINKGO) $(GINKGO_FLAGS) -focus="odo app command tests" tests/integration/
.PHONY: test-cmd-cmp
test-cmd-cmp: ## Run odo component command tests
$(RUN_GINKGO) $(GINKGO_FLAGS) -focus="odo component command tests" tests/integration/
.PHONY: test-cmd-cmp-sub
test-cmd-cmp-sub: ## Run odo component subcommands tests
$(RUN_GINKGO) $(GINKGO_FLAGS) -focus="odo sub component command tests" tests/integration/
.PHONY: test-cmd-pref-config
test-cmd-pref-config: ## Run odo preference and config command tests
$(RUN_GINKGO) $(GINKGO_FLAGS) -focus="odo preference and config command tests" tests/integration/
.PHONY: test-cmd-push
test-cmd-push: ## Run odo push command tests
$(RUN_GINKGO) $(GINKGO_FLAGS) -focus="odo push command tests" tests/integration/
.PHONY: test-plugin-handler
test-plugin-handler: ## Run odo plugin handler tests
$(RUN_GINKGO) $(GINKGO_FLAGS) -focus="odo plugin functionality" tests/integration/
@@ -246,14 +226,6 @@ test-cmd-devfile-registry: ## Run odo devfile registry command tests
.PHONY: test-cmd-devfile-test
test-cmd-devfile-test: ## Run odo devfile test command tests
$(RUN_GINKGO) $(GINKGO_FLAGS) -focus="odo devfile test command tests" tests/integration/devfile/
.PHONY: test-cmd-storage
test-cmd-storage: ## Run odo storage command tests
$(RUN_GINKGO) $(GINKGO_FLAGS) -focus="odo storage command tests" tests/integration/
.PHONY: test-cmd-url
test-cmd-url: ## Run odo url command tests
$(RUN_GINKGO) $(GINKGO_FLAGS) -focus="odo url command tests" tests/integration/
.PHONY: test-cmd-devfile-url
test-cmd-devfile-url: ## Run odo url devfile command tests
@@ -293,29 +265,12 @@ test-cmd-debug: ## Run odo debug command tests
.PHONY: test-integration
test-integration: ## Run command's integration tests irrespective of service catalog status in the cluster.
$(RUN_GINKGO) $(GINKGO_FLAGS) tests/integration/
$(RUN_GINKGO) $(GINKGO_FLAGS_SERIAL) tests/integration/debug/
.PHONY: test-integration-devfile
test-integration-devfile: ## Run devfile integration tests
$(RUN_GINKGO) $(GINKGO_FLAGS) tests/integration/devfile/
$(RUN_GINKGO) $(GINKGO_FLAGS_SERIAL) tests/integration/devfile/debug/
.PHONY: test-e2e-beta
test-e2e-beta: ## Run core beta flow e2e tests
$(RUN_GINKGO) $(GINKGO_FLAGS) -focus="odo core beta flow" tests/e2escenarios/
.PHONY: test-e2e-java
test-e2e-java: ## Run java e2e tests
$(RUN_GINKGO) $(GINKGO_FLAGS) -focus="odo java e2e tests" tests/e2escenarios/
.PHONY: test-e2e-source
test-e2e-source: ## Run source e2e tests
$(RUN_GINKGO) $(GINKGO_FLAGS) -focus="odo source e2e tests" tests/e2escenarios/
.PHONY: test-e2e-images
test-e2e-images: ## Run supported images e2e tests
$(RUN_GINKGO) $(GINKGO_FLAGS) -focus="odo supported images e2e tests" tests/e2escenarios/
.PHONY: test-e2e-devfile
test-e2e-devfile: ## Run devfile e2e tests: odo devfile supported tests
$(RUN_GINKGO) $(GINKGO_FLAGS) -focus="odo devfile supported tests" tests/e2escenarios/

View File

@@ -406,15 +406,5 @@ NOTE: To see the number of available integration test files for validation, pres
(E2e) End to end test run behaves in the similar way like integration test does. To see the number of available e2e test file for execution, press tab just after writing `make test-e2e-`. For e2e suite level execution of all e2e test spec use `make test-e2e-all`. For example
* To run the java e2e test in parallel, on a test cluster (By default the component test will run in parallel on two ginkgo test node):
+
----
$ make test-e2e-java
----
+
* To run the java e2e test sequentially or on single ginkgo test node:
+
----
$ TEST_EXEC_NODES=1 make test-e2e-java
----

View File

@@ -188,7 +188,6 @@ func odoRootCmd(name, fullName string) *cobra.Command {
component.NewCmdList(component.ListRecommendedCommandName, util.GetFullName(fullName, component.ListRecommendedCommandName)),
component.NewCmdLog(component.LogRecommendedCommandName, util.GetFullName(fullName, component.LogRecommendedCommandName)),
component.NewCmdPush(component.PushRecommendedCommandName, util.GetFullName(fullName, component.PushRecommendedCommandName)),
component.NewCmdUpdate(component.UpdateRecommendedCommandName, util.GetFullName(fullName, component.UpdateRecommendedCommandName)),
component.NewCmdWatch(component.WatchRecommendedCommandName, util.GetFullName(fullName, component.WatchRecommendedCommandName)),
component.NewCmdStatus(component.StatusRecommendedCommandName, util.GetFullName(fullName, component.StatusRecommendedCommandName)),
component.NewCmdExec(component.ExecRecommendedCommandName, util.GetFullName(fullName, component.ExecRecommendedCommandName)),

View File

@@ -49,16 +49,6 @@ func NewCommonPushOptions() *CommonPushOptions {
}
}
//InitConfigFromContext initializes localconfiginfo from the context
func (cpo *CommonPushOptions) InitConfigFromContext() error {
var err error
cpo.LocalConfigInfo, err = config.NewLocalConfigInfo(cpo.componentContext)
if err != nil {
return err
}
return nil
}
//InitEnvInfoFromContext initializes envinfo from the context
func (cpo *CommonPushOptions) InitEnvInfoFromContext() (err error) {
cpo.EnvSpecificInfo, err = envinfo.NewEnvSpecificInfo(cpo.componentContext)

View File

@@ -6,15 +6,9 @@ import (
"github.com/openshift/odo/pkg/util"
"github.com/openshift/odo/pkg/component"
"github.com/openshift/odo/pkg/log"
"github.com/openshift/odo/pkg/occlient"
"github.com/openshift/odo/pkg/odo/util/completion"
"github.com/openshift/odo/pkg/url"
"github.com/pkg/errors"
"github.com/openshift/odo/pkg/odo/genericclioptions"
odoutil "github.com/openshift/odo/pkg/odo/util"
"github.com/openshift/odo/pkg/odo/util/completion"
"github.com/spf13/cobra"
)
@@ -57,7 +51,6 @@ func NewCmdComponent(name, fullName string) *cobra.Command {
listCmd := NewCmdList(ListRecommendedCommandName, odoutil.GetFullName(fullName, ListRecommendedCommandName))
logCmd := NewCmdLog(LogRecommendedCommandName, odoutil.GetFullName(fullName, LogRecommendedCommandName))
pushCmd := NewCmdPush(PushRecommendedCommandName, odoutil.GetFullName(fullName, PushRecommendedCommandName))
updateCmd := NewCmdUpdate(UpdateRecommendedCommandName, odoutil.GetFullName(fullName, UpdateRecommendedCommandName))
watchCmd := NewCmdWatch(WatchRecommendedCommandName, odoutil.GetFullName(fullName, WatchRecommendedCommandName))
testCmd := NewCmdTest(TestRecommendedCommandName, odoutil.GetFullName(fullName, TestRecommendedCommandName))
execCmd := NewCmdExec(ExecRecommendedCommandName, odoutil.GetFullName(fullName, ExecRecommendedCommandName))
@@ -77,7 +70,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, linkCmd, unlinkCmd, listCmd, logCmd, pushCmd, updateCmd, watchCmd, execCmd)
componentCmd.AddCommand(componentGetCmd, createCmd, deleteCmd, describeCmd, linkCmd, unlinkCmd, listCmd, logCmd, pushCmd, watchCmd, execCmd)
componentCmd.AddCommand(testCmd, statusCmd)
// Add a defined annotation in order to appear in the help menu
@@ -93,23 +86,3 @@ func AddComponentFlag(cmd *cobra.Command) {
cmd.Flags().String(genericclioptions.ComponentFlagName, "", "Component, defaults to active component.")
completion.RegisterCommandFlagHandler(cmd, "component", completion.ComponentNameCompletionHandler)
}
// printDeleteComponentInfo will print things which will be deleted
func printDeleteComponentInfo(client *occlient.Client, componentName string, appName string, projectName string) error {
componentDesc, err := component.GetComponent(client, componentName, appName, projectName)
if err != nil {
return errors.Wrap(err, "unable to get component description")
}
if len(componentDesc.Spec.URL) != 0 {
log.Info("This component has following urls that will be deleted with component")
ul, err := url.ListPushed(client, componentDesc.Name, appName)
if err != nil {
return errors.Wrap(err, "Could not get url list")
}
for _, u := range ul.Items {
log.Info("URL named", u.GetName(), "with host", u.Spec.Host, "having protocol", u.Spec.Protocol, "at port", u.Spec.Port)
}
}
return nil
}

View File

@@ -16,11 +16,9 @@ import (
"github.com/openshift/odo/pkg/component"
"github.com/openshift/odo/pkg/config"
"github.com/openshift/odo/pkg/devfile"
"github.com/openshift/odo/pkg/devfile/convert"
"github.com/openshift/odo/pkg/devfile/validate"
"github.com/openshift/odo/pkg/envinfo"
"github.com/openshift/odo/pkg/log"
"github.com/openshift/odo/pkg/machineoutput"
appCmd "github.com/openshift/odo/pkg/odo/cli/application"
"github.com/openshift/odo/pkg/odo/cli/component/ui"
projectCmd "github.com/openshift/odo/pkg/odo/cli/project"
@@ -37,17 +35,12 @@ import (
// CreateOptions encapsulates create options
type CreateOptions struct {
componentSettings config.ComponentSettings
componentBinary string
componentGit string
componentGitRef string
componentContext string
componentPorts []string
componentEnvVars []string
appName string
interactive bool
now bool
forceS2i bool
componentContext string
componentPorts []string
componentEnvVars []string
appName string
interactive bool
now bool
*PushOptions
devfileMetadata DevfileMetadata
@@ -82,17 +75,13 @@ const CreateRecommendedCommandName = "create"
const LocalDirectoryDefaultLocation = "./"
var (
envFile = filepath.Join(".odo", "env", "env.yaml")
configFile = filepath.Join(".odo", "config.yaml")
envDir = filepath.Join(".odo", "env")
envFile = filepath.Join(".odo", "env", "env.yaml")
envDir = filepath.Join(".odo", "env")
)
// EnvFilePath is the path of env file for devfile component
var EnvFilePath = filepath.Join(LocalDirectoryDefaultLocation, envFile)
// ConfigFilePath is the path of config.yaml for s2i component
var ConfigFilePath = filepath.Join(LocalDirectoryDefaultLocation, configFile)
var createLongDesc = ktemplates.LongDesc(`Create a configuration describing a component.`)
var createExample = ktemplates.Examples(`# Create a new Node.JS component with existing sourcecode as well as specifying a name
@@ -115,14 +104,6 @@ odo catalog list components
# Create new Node.js component named 'frontend' with the source in './frontend' directory
%[1]s nodejs frontend --context ./frontend
# Create new Java component with binary named sample.jar in './target' directory; this flag is specific to S2I
# DEPRECATED: Use the devfile to create a component
%[1]s java:8 --s2i --binary target/sample.jar
# Create new Node.js component with source from remote git repository; this flag is specific to S2I
# DEPRECATED: Use the devfile to create a component
%[1]s nodejs --s2i --git https://github.com/openshift/nodejs-ex.git
# Create new Node.js component with custom ports and environment variables
%[1]s nodejs --port 8080,8100/tcp,9100/udp --env key=value,key1=value1
@@ -138,118 +119,6 @@ func NewCreateOptions() *CreateOptions {
}
}
func (co *CreateOptions) setComponentSourceAttributes() (err error) {
// Set the correct application context
co.componentSettings.Application = &(co.Context.Application)
// By default we set the source as LOCAL (if --local, --binary or --git isn't passed)
componentSourceType := config.LOCAL
// If --local, --binary or --git is passed, let's set the correct source type.
if len(co.componentBinary) != 0 {
componentSourceType = config.BINARY
} else if len(co.componentGit) != 0 {
componentSourceType = config.GIT
}
co.componentSettings.SourceType = &componentSourceType
// Here we set the correct source path for each type
switch componentSourceType {
// --binary
case config.BINARY:
// Convert componentContext to absolute path, so it can be safely used in filepath.Rel
// even when it is not set (empty). In this case filepath.Abs will return current directory.
absContext, err := filepath.Abs(co.componentContext)
if err != nil {
return err
}
absPath, err := filepath.Abs(co.componentBinary)
if err != nil {
return err
}
// we need to store the SourceLocation relative to the componentContext
relativePathToSource, err := filepath.Rel(absContext, absPath)
if err != nil {
return err
}
co.componentSettings.SourceLocation = &relativePathToSource
// --git
case config.GIT:
co.componentSettings.SourceLocation = &(co.componentGit)
componentSourceType = config.GIT
co.componentSettings.SourceType = &componentSourceType
// --local / default
case config.LOCAL:
directory := LocalDirectoryDefaultLocation
co.componentSettings.SourceLocation = &directory
// Error out by default if no type of sources were passed..
default:
return fmt.Errorf("the source can be either --binary or --local or --git")
}
// Set the Git reference if passed
if len(co.componentGitRef) != 0 {
co.componentSettings.Ref = &(co.componentGitRef)
}
// Error out if reference is passed but no --git flag passed
if len(co.componentGit) == 0 && len(co.componentGitRef) != 0 {
return fmt.Errorf("the --ref flag is only valid for --git flag")
}
return
}
func (co *CreateOptions) setComponentName(args []string) (err error) {
componentImageName, componentType, _, _ := util.ParseComponentImageName(args[0])
co.componentSettings.Type = &componentImageName
if len(args) == 2 {
co.componentSettings.Name = &args[1]
return
}
if co.componentSettings.SourceType == nil {
return errors.Wrap(err, "component type is mandatory parameter to generate a default component name")
}
componentName, err := createDefaultComponentName(
co.Context,
componentType,
*(co.componentSettings.SourceType),
co.componentContext,
)
if err != nil {
return err
}
co.componentSettings.Name = &componentName
return
}
func getSourceLocation(componentContext string, currentDirectory string) (string, error) {
// After getting the path relative to the current directory, we set the SourceLocation
sourceLocation, err := filepath.Rel(currentDirectory, componentContext)
if err != nil {
return "", errors.Wrapf(err, "unable to get a path relative to the current directory")
}
// If the paths are the same (currentDirectory vs co.componentSettings.SourceLocation)
// then we use the default location
if sourceLocation == "." {
return LocalDirectoryDefaultLocation, nil
}
return sourceLocation, nil
}
func createDefaultComponentName(context *genericclioptions.Context, componentType string, sourceType config.SrcType, sourcePath string) (string, error) {
// Retrieve the componentName, if the componentName isn't specified, we will use the default image name
var err error
@@ -284,65 +153,10 @@ func createDefaultComponentName(context *genericclioptions.Context, componentTyp
return componentName, nil
}
func (co *CreateOptions) checkConflictingFlags() (err error) {
if err = co.checkConflictingS2IFlags(); err != nil {
return
}
if err = co.checkConflictingDevfileFlags(); err != nil {
return
}
return nil
}
func (co *CreateOptions) checkConflictingS2IFlags() error {
if !co.forceS2i {
errorString := "flag --%s, requires --s2i flag to be set, when deploying S2I (Source-to-Image) components."
var flagName string
if len(co.componentBinary) != 0 {
flagName = "binary"
} else if len(co.componentGit) != 0 {
flagName = "git"
} else if len(co.componentEnvVars) != 0 {
flagName = "env"
} else if len(co.componentPorts) != 0 {
flagName = "port"
}
if len(flagName) != 0 {
return errors.New(fmt.Sprintf(errorString, flagName))
}
}
return nil
}
func (co *CreateOptions) checkConflictingDevfileFlags() error {
if co.forceS2i {
errorString := "you can't set --s2i flag as true if you want to use the %s via --%s flag"
var flagName string
if len(co.devfileMetadata.devfilePath.value) != 0 {
flagName = "devfile"
} else if len(co.devfileMetadata.devfileRegistry.Name) != 0 {
flagName = "registry"
} else if len(co.devfileMetadata.token) != 0 {
flagName = "token"
} else if len(co.devfileMetadata.starter) != 0 {
flagName = "starter"
}
if len(flagName) != 0 {
return errors.New(fmt.Sprintf(errorString, flagName, flagName))
}
}
return nil
}
// Complete completes create args
func (co *CreateOptions) Complete(name string, cmd *cobra.Command, args []string) (err error) {
if co.forceS2i || co.now {
if co.now {
// this populates the LocalConfigInfo as well
co.Context, err = genericclioptions.NewContextCreatingAppIfNeeded(cmd)
if err != nil {
@@ -351,38 +165,15 @@ func (co *CreateOptions) Complete(name string, cmd *cobra.Command, args []string
} else {
co.Context = genericclioptions.NewOfflineDevfileContext(cmd)
}
err = co.checkConflictingFlags()
if err != nil {
return
}
if co.forceS2i {
// Note: Remove this deprecation warning once the S2I cleanup is done, see https://github.com/openshift/odo/issues/4932.
log.Deprecate("S2I components", "consider creating a devfile component instead")
}
var catalogList catalog.ComponentTypeList
if co.forceS2i {
client := co.Client
catalogList, err = catalog.ListComponents(client)
if err != nil {
return err
}
}
// Configure the context
if co.componentContext != "" {
DevfilePath = filepath.Join(co.componentContext, devFile)
EnvFilePath = filepath.Join(co.componentContext, envFile)
ConfigFilePath = filepath.Join(co.componentContext, configFile)
co.PushOptions.componentContext = co.componentContext
}
co.DevfilePath = DevfilePath
if util.CheckPathExists(ConfigFilePath) {
return errors.New("this directory already contains a component")
}
if util.CheckPathExists(EnvFilePath) && util.CheckPathExists(co.DevfilePath) {
return errors.New("this directory already contains a component")
}
@@ -408,189 +199,184 @@ func (co *CreateOptions) Complete(name string, cmd *cobra.Command, args []string
isDevfileRegistryPresent := true // defaulted to true since odo ships with a default registry set
var catalogDevfileList catalog.DevfileComponentTypeList
// If not using --s2i
if !co.forceS2i {
// Validate user specify devfile path
if co.devfileMetadata.devfilePath.value != "" {
fileErr := util.ValidateFile(co.devfileMetadata.devfilePath.value)
urlErr := util.ValidateURL(co.devfileMetadata.devfilePath.value)
if fileErr != nil && urlErr != nil {
return errors.Errorf("the devfile path you specify is invalid with either file error \"%v\" or url error \"%v\"", fileErr, urlErr)
} else if fileErr == nil {
co.devfileMetadata.devfilePath.protocol = "file"
} else if urlErr == nil {
co.devfileMetadata.devfilePath.protocol = "http(s)"
}
}
// Validate user specify registry
if co.devfileMetadata.devfileRegistry.Name != "" {
// Validate user specify devfile path
if co.devfileMetadata.devfilePath.value != "" {
fileErr := util.ValidateFile(co.devfileMetadata.devfilePath.value)
urlErr := util.ValidateURL(co.devfileMetadata.devfilePath.value)
if fileErr != nil && urlErr != nil {
return errors.Errorf("the devfile path you specify is invalid with either file error \"%v\" or url error \"%v\"", fileErr, urlErr)
} else if fileErr == nil {
co.devfileMetadata.devfilePath.protocol = "file"
} else if urlErr == nil {
co.devfileMetadata.devfilePath.protocol = "http(s)"
return errors.New("you can't specify registry via --registry if you want to use the devfile that is specified via --devfile")
}
registryList, err := catalog.GetDevfileRegistries(co.devfileMetadata.devfileRegistry.Name)
if err != nil {
return errors.Wrap(err, "failed to get registry")
}
if len(registryList) == 0 {
return errors.Errorf("registry %s doesn't exist, please specify a valid registry via --registry", co.devfileMetadata.devfileRegistry.Name)
}
}
// Can't use the existing devfile or download devfile from registry, go to interactive mode
if len(args) == 0 && !util.CheckPathExists(co.DevfilePath) && co.devfileMetadata.devfilePath.value == "" {
co.interactive = true
}
var componentType string
var componentName string
var componentNamespace string
if co.interactive {
// Interactive mode
// Get available devfile components for checking devfile compatibility
catalogDevfileList, err = catalog.ListDevfileComponents(co.devfileMetadata.devfileRegistry.Name)
if err != nil {
return err
}
if len(catalogDevfileList.DevfileRegistries) == 0 {
isDevfileRegistryPresent = false
log.Warning("Registry is empty, please run `odo registry add <registry name> <registry URL>` to add a registry\n")
}
if isDevfileRegistryPresent {
// Component type: We provide devfile component list to let user choose
componentType = ui.SelectDevfileComponentType(catalogDevfileList.Items)
// Component name: User needs to specify the component name, by default it is component type that user chooses
componentName = ui.EnterDevfileComponentName(componentType)
// Component namespace: User needs to specify component namespace, by default it is the current active namespace
if cmd.Flags().Changed("project") {
componentNamespace, err = cmd.Flags().GetString("project")
if err != nil {
return err
}
} else {
client, err := genericclioptions.Client()
// if the user is logged in or if we have cluster information, display the default project
if err == nil {
componentNamespace = ui.EnterDevfileComponentProject(client.GetCurrentProjectName())
}
}
}
// Validate user specify registry
if co.devfileMetadata.devfileRegistry.Name != "" {
} else {
// Direct mode (User enters the full command)
if co.devfileMetadata.devfilePath.value != "" {
return errors.New("you can't specify registry via --registry if you want to use the devfile that is specified via --devfile")
if util.CheckPathExists(co.DevfilePath) || co.devfileMetadata.devfilePath.value != "" {
// Use existing devfile directly
if len(args) > 1 {
return errors.Errorf("accepts between 0 and 1 arg when using existing devfile, received %d", len(args))
}
registryList, err := catalog.GetDevfileRegistries(co.devfileMetadata.devfileRegistry.Name)
if err != nil {
return errors.Wrap(err, "failed to get registry")
// If user can use existing devfile directly, the first arg is component name instead of component type
if len(args) == 1 {
componentName = args[0]
} else {
// If there is an existing devfile, and no component name is passed, parse it from the devfile,
// and assign the value if the metadata name is set
devfileObj, err := devfile.ParseFromFile(DevfilePath)
if err == nil && devfileObj.GetMetadataName() != "" {
componentName = devfileObj.GetMetadataName()
} else {
// If the metadata name is not available, then assign the current directory name to component
currentDirPath, err := os.Getwd()
if err != nil {
return err
}
currentDirName := filepath.Base(currentDirPath)
componentName = currentDirName
}
}
if len(registryList) == 0 {
return errors.Errorf("registry %s doesn't exist, please specify a valid registry via --registry", co.devfileMetadata.devfileRegistry.Name)
co.devfileMetadata.devfileSupport = true
} else if len(args) > 0 {
// Download devfile from registry
// Component type: Get from full command's first argument (mandatory in direct mode)
componentType = args[0]
// Component name: Get from full command's second argument (optional in direct mode), by default it is a generated name if second arg is not provided
if len(args) == 2 {
componentName = args[1]
} else {
var err error
componentName, err = createDefaultComponentName(
co.Context,
componentType,
config.LOCAL, // always local for devfile
co.componentContext,
)
if err != nil {
return err
}
}
}
// Can't use the existing devfile or download devfile from registry, go to interactive mode
if len(args) == 0 && !util.CheckPathExists(co.DevfilePath) && co.devfileMetadata.devfilePath.value == "" {
co.interactive = true
}
var componentType string
var componentName string
var componentNamespace string
if co.interactive {
// Interactive mode
// Get available devfile components for checking devfile compatibility
catalogDevfileList, err = catalog.ListDevfileComponents(co.devfileMetadata.devfileRegistry.Name)
if err != nil {
return err
}
if co.devfileMetadata.devfileRegistry.Name != "" && catalogDevfileList.Items == nil {
return errors.Errorf("can't create devfile component from registry %s", co.devfileMetadata.devfileRegistry.Name)
}
if len(catalogDevfileList.DevfileRegistries) == 0 {
isDevfileRegistryPresent = false
log.Warning("Registry is empty, please run `odo registry add <registry name> <registry URL>` to add a registry\n")
log.Warning("Registry list is empty, please run `odo registry add <registry name> <registry URL>` to add a registry\n")
}
if isDevfileRegistryPresent {
// Component type: We provide devfile component list to let user choose
componentType = ui.SelectDevfileComponentType(catalogDevfileList.Items)
// Component name: User needs to specify the component name, by default it is component type that user chooses
componentName = ui.EnterDevfileComponentName(componentType)
// Component namespace: User needs to specify component namespace, by default it is the current active namespace
if cmd.Flags().Changed("project") {
componentNamespace, err = cmd.Flags().GetString("project")
if err != nil {
return err
}
} else {
client, err := genericclioptions.Client()
// if the user is logged in or if we have cluster information, display the default project
if err == nil {
componentNamespace = ui.EnterDevfileComponentProject(client.GetCurrentProjectName())
}
}
}
} else {
// Direct mode (User enters the full command)
if util.CheckPathExists(co.DevfilePath) || co.devfileMetadata.devfilePath.value != "" {
// Use existing devfile directly
if len(args) > 1 {
return errors.Errorf("accepts between 0 and 1 arg when using existing devfile, received %d", len(args))
}
// If user can use existing devfile directly, the first arg is component name instead of component type
if len(args) == 1 {
componentName = args[0]
} else {
// If there is an existing devfile, and no component name is passed, parse it from the devfile,
// and assign the value if the metadata name is set
devfileObj, err := devfile.ParseFromFile(DevfilePath)
if err == nil && devfileObj.GetMetadataName() != "" {
componentName = devfileObj.GetMetadataName()
} else {
// If the metadata name is not available, then assign the current directory name to component
currentDirPath, err := os.Getwd()
if err != nil {
return err
}
currentDirName := filepath.Base(currentDirPath)
componentName = currentDirName
}
}
co.devfileMetadata.devfileSupport = true
} else if len(args) > 0 {
// Download devfile from registry
// Component type: Get from full command's first argument (mandatory in direct mode)
componentType = args[0]
// Component name: Get from full command's second argument (optional in direct mode), by default it is a generated name if second arg is not provided
if len(args) == 2 {
componentName = args[1]
} else {
var err error
componentName, err = createDefaultComponentName(
co.Context,
componentType,
config.LOCAL, // always local for devfile
co.componentContext,
)
if err != nil {
return err
}
}
// Get available devfile components for checking devfile compatibility
catalogDevfileList, err = catalog.ListDevfileComponents(co.devfileMetadata.devfileRegistry.Name)
if err != nil {
return err
}
if co.devfileMetadata.devfileRegistry.Name != "" && catalogDevfileList.Items == nil {
return errors.Errorf("can't create devfile component from registry %s", co.devfileMetadata.devfileRegistry.Name)
}
if len(catalogDevfileList.DevfileRegistries) == 0 {
isDevfileRegistryPresent = false
log.Warning("Registry list is empty, please run `odo registry add <registry name> <registry URL>` to add a registry\n")
}
}
componentNamespace = co.Context.Project
}
// Set devfileMetadata struct
co.devfileMetadata.componentType = componentType
co.devfileMetadata.componentName = strings.ToLower(componentName)
co.devfileMetadata.componentNamespace = strings.ToLower(componentNamespace)
componentNamespace = co.Context.Project
}
if util.CheckPathExists(co.DevfilePath) || co.devfileMetadata.devfilePath.value != "" {
// Categorize the sections
log.Info("Devfile Object Validation")
// Set devfileMetadata struct
co.devfileMetadata.componentType = componentType
co.devfileMetadata.componentName = strings.ToLower(componentName)
co.devfileMetadata.componentNamespace = strings.ToLower(componentNamespace)
var devfileAbsolutePath string
if util.CheckPathExists(co.DevfilePath) || co.devfileMetadata.devfilePath.protocol == "file" {
var devfilePath string
if util.CheckPathExists(co.DevfilePath) {
devfilePath = co.DevfilePath
} else {
devfilePath = co.devfileMetadata.devfilePath.value
}
devfileAbsolutePath, err = filepath.Abs(devfilePath)
if err != nil {
return err
}
} else if co.devfileMetadata.devfilePath.protocol == "http(s)" {
devfileAbsolutePath = co.devfileMetadata.devfilePath.value
if util.CheckPathExists(co.DevfilePath) || co.devfileMetadata.devfilePath.value != "" {
// Categorize the sections
log.Info("Devfile Object Validation")
var devfileAbsolutePath string
if util.CheckPathExists(co.DevfilePath) || co.devfileMetadata.devfilePath.protocol == "file" {
var devfilePath string
if util.CheckPathExists(co.DevfilePath) {
devfilePath = co.DevfilePath
} else {
devfilePath = co.devfileMetadata.devfilePath.value
}
devfileSpinner := log.Spinnerf("Creating a devfile component from devfile path: %s", devfileAbsolutePath)
defer devfileSpinner.End(true)
// Initialize envinfo
err = co.InitEnvInfoFromContext()
devfileAbsolutePath, err = filepath.Abs(devfilePath)
if err != nil {
return err
}
return nil
} else if co.devfileMetadata.devfilePath.protocol == "http(s)" {
devfileAbsolutePath = co.devfileMetadata.devfilePath.value
}
devfileSpinner := log.Spinnerf("Creating a devfile component from devfile path: %s", devfileAbsolutePath)
defer devfileSpinner.End(true)
// Initialize envinfo
err = co.InitEnvInfoFromContext()
if err != nil {
return err
}
return nil
}
if isDevfileRegistryPresent {
@@ -602,11 +388,9 @@ func (co *CreateOptions) Complete(name string, cmd *cobra.Command, args []string
hasComponent := false
var devfileExistSpinner *log.Status
if !co.forceS2i {
log.Info("Devfile Object Validation")
devfileExistSpinner = log.Spinner("Checking devfile existence")
defer devfileExistSpinner.End(false)
}
log.Info("Devfile Object Validation")
devfileExistSpinner = log.Spinner("Checking devfile existence")
defer devfileExistSpinner.End(false)
for _, devfileComponent := range catalogDevfileList.Items {
if co.devfileMetadata.componentType == devfileComponent.Name {
@@ -618,28 +402,13 @@ func (co *CreateOptions) Complete(name string, cmd *cobra.Command, args []string
}
}
if co.forceS2i && hasComponent {
s2iOverride := false
for _, item := range catalogList.Items {
if item.Name == co.devfileMetadata.componentType {
s2iOverride = true
break
}
}
if !s2iOverride {
return errors.New("cannot select a devfile type component with --s2i flag")
}
if hasComponent {
devfileExistSpinner.End(true)
} else {
devfileExistSpinner.End(false)
}
if !co.forceS2i {
if hasComponent {
devfileExistSpinner.End(true)
} else {
devfileExistSpinner.End(false)
}
}
if co.devfileMetadata.devfileSupport && !co.forceS2i {
if co.devfileMetadata.devfileSupport {
registrySpinner := log.Spinnerf("Creating a devfile component from registry: %s", co.devfileMetadata.devfileRegistry.Name)
if registryUtil.IsGitBasedRegistry(co.devfileMetadata.devfileRegistry.URL) {
registryUtil.PrintGitRegistryDeprecationWarning()
@@ -655,69 +424,8 @@ func (co *CreateOptions) Complete(name string, cmd *cobra.Command, args []string
return nil
}
// Currently only devfile component supports --registry flag, so if user specifies --registry when creating devfile component,
// we should error out instead of running s2i component code and throw warning message
if co.devfileMetadata.devfileRegistry.Name != "" {
return errors.Errorf("devfile component type %s is not supported, please run `odo catalog list components` for a list of supported devfile component types", co.devfileMetadata.componentType)
}
return fmt.Errorf("devfile component type %q is not supported, please run `odo catalog list components` for a list of supported devfile component types", co.devfileMetadata.componentType)
if !co.forceS2i {
log.Warningf("Devfile component type %s is not supported, please run `odo catalog list components` for a list of supported devfile component types", co.devfileMetadata.componentType)
}
}
if len(args) == 0 || !cmd.HasFlags() {
co.interactive = true
}
// the component type was not found for devfile components
// fallback to s2i
co.Context, err = genericclioptions.NewContextCreatingAppIfNeeded(cmd)
if err != nil {
return err
}
// Do not execute S2I specific code on Kubernetes Cluster or Docker
// return from here, if it is not an openshift cluster.
var openshiftCluster bool
openshiftCluster, _ = co.Client.IsImageStreamSupported()
if !openshiftCluster {
return errors.New("component type not found")
}
// check to see if config file exists or not, if it does that
// means we shouldn't allow the user to override the current component
if co.LocalConfigInfo.Exists() {
return errors.New("this directory already contains a component")
}
co.componentSettings = co.LocalConfigInfo.GetComponentSettings()
// Below code is for INTERACTIVE mode
if co.interactive {
if len(catalogList.Items) == 0 {
catalogList, err = catalog.ListComponents(co.Client)
if err != nil {
return err
}
}
err := co.SetComponentSettingsInteractively(catalogList)
if err != nil {
return err
}
} else {
if err := co.SetComponentSettings(args); err != nil {
return err
}
}
if co.now {
co.ResolveSrcAndConfigFlags()
err = co.ResolveProject(co.Context.Project)
if err != nil {
return err
}
}
return
}
@@ -727,62 +435,17 @@ func (co *CreateOptions) Validate() (err error) {
log.Info("Validation")
if !co.forceS2i && co.devfileMetadata.devfileSupport {
// Validate if the devfile component name that user wants to create adheres to the k8s naming convention
spinner := log.Spinner("Validating if devfile name is correct")
defer spinner.End(false)
// Validate if the devfile component name that user wants to create adheres to the k8s naming convention
spinner := log.Spinner("Validating if devfile name is correct")
defer spinner.End(false)
err = util.ValidateK8sResourceName("component name", co.devfileMetadata.componentName)
if err != nil {
return err
}
spinner.End(true)
return nil
}
supported, err := catalog.IsComponentTypeSupported(co.Context.Client, *co.componentSettings.Type)
err = util.ValidateK8sResourceName("component name", co.devfileMetadata.componentName)
if err != nil {
return err
}
if !supported {
log.Infof("Warning: %s is not fully supported by odo, and it is not guaranteed to work", *co.componentSettings.Type)
}
spinner.End(true)
s := log.Spinner("Validating component")
defer s.End(false)
if err := component.ValidateComponentCreateRequest(co.Context.Client, co.componentSettings, co.componentContext); err != nil {
return err
}
s.End(true)
return nil
}
func (co *CreateOptions) s2iRun() (err error) {
err = co.LocalConfigInfo.SetComponentSettings(co.componentSettings)
if err != nil {
return errors.Wrapf(err, "failed to persist the component settings to config file")
}
if co.now {
co.Context, co.LocalConfigInfo, err = genericclioptions.UpdatedContext(co.Context)
if err != nil {
return errors.Wrap(err, "unable to retrieve updated local config")
}
err = co.SetSourceInfo()
if err != nil {
return errors.Wrap(err, "unable to set source information")
}
err = co.Push()
if err != nil {
return errors.Wrapf(err, "failed to push the changes")
}
} else {
log.Italic("\nPlease use `odo push` command to create the component with source deployed")
}
return nil
}
@@ -960,93 +623,17 @@ func (co *CreateOptions) devfileRun(cmd *cobra.Command) (err error) {
// Run has the logic to perform the required actions as part of command
func (co *CreateOptions) Run(cmd *cobra.Command) (err error) {
// By default we run Devfile
if !co.forceS2i && co.devfileMetadata.devfileSupport {
if scontext.GetTelemetryStatus(cmd.Context()) {
scontext.SetComponentType(cmd.Context(), co.devfileMetadata.componentType)
}
err := co.devfileRun(cmd)
if err != nil {
return err
}
if log.IsJSON() {
return co.DevfileJSON()
}
return nil
}
// Add component type for s2i components
if scontext.GetTelemetryStatus(cmd.Context()) {
scontext.SetComponentType(cmd.Context(), *co.componentSettings.Type)
scontext.SetComponentType(cmd.Context(), co.devfileMetadata.componentType)
}
// we only do conversion if the --s2i is provided and the component is not of --git type
if co.forceS2i && len(co.componentGit) == 0 && len(co.componentBinary) == 0 {
log.Info("Conversion")
// do the conversion
// lets fill the localConfigInfo as we are using that as an adapter
co.LocalConfigInfo.SetComponentSettingsWithoutFileWrite(co.componentSettings)
if err := convert.GenerateDevfileYaml(co.Client, co.LocalConfigInfo, co.componentContext); err != nil {
return err
}
if _, err := convert.GenerateEnvYaml(co.Client, co.LocalConfigInfo, co.componentContext); err != nil {
return err
}
log.Success("Successfully generated devfile.yaml and env.yaml for provided S2I component")
if co.now {
err = co.InitEnvInfoFromContext()
if err != nil {
return err
}
err = co.DevfilePush()
if err != nil {
return fmt.Errorf("failed to push changes: %w", err)
}
} else {
log.Italic("\nPlease use `odo push` command to create the component with source deployed")
}
if log.IsJSON() {
return co.DevfileJSON()
}
return nil
}
// If not, we run s2i (if the --s2i parameter has been passed in).
// It's implied that we have passed it in if Devfile did not run above
err = co.s2iRun()
err = co.devfileRun(cmd)
if err != nil {
return err
}
if log.IsJSON() {
var componentDesc component.Component
co.Context, co.LocalConfigInfo, err = genericclioptions.UpdatedContext(co.Context)
if err != nil {
return err
}
state := component.GetComponentState(co.Client, *co.componentSettings.Name, co.Context.Application)
if state == component.StateTypeNotPushed || state == component.StateTypeUnknown {
componentDesc, err = component.GetComponentFromConfig(co.LocalConfigInfo)
componentDesc.Status.State = state
if err != nil {
return err
}
} else {
componentDesc, err = component.GetComponent(co.Context.Client, *co.componentSettings.Name, co.Context.Application, co.Context.Project)
if err != nil {
return err
}
}
componentDesc.Spec.Ports, err = co.LocalConfigInfo.GetComponentPorts()
if err != nil {
return err
}
machineoutput.OutputSuccess(componentDesc)
return co.DevfileJSON()
}
return
return nil
}
// NewCmdCreate implements the create odo command
@@ -1063,9 +650,6 @@ func NewCmdCreate(name, fullName string) *cobra.Command {
genericclioptions.GenericRun(co, cmd, args)
},
}
componentCreateCmd.Flags().StringVarP(&co.componentBinary, "binary", "b", "", "Create a binary file component component using given artifact. Works only with Java components. File needs to be in the context directory. Specific to S2I components.")
componentCreateCmd.Flags().StringVarP(&co.componentGit, "git", "g", "", "Create a git component using this repository. Specific to S2I components.")
componentCreateCmd.Flags().StringVarP(&co.componentGitRef, "ref", "r", "", "Use a specific ref e.g. commit, branch or tag of the git repository (only valid for --git components)")
genericclioptions.AddContextFlag(componentCreateCmd, &co.componentContext)
componentCreateCmd.Flags().StringSliceVarP(&co.componentPorts, "port", "p", []string{}, "Ports to be used when the component is created (ex. 8080,8100/tcp,9100/udp)")
componentCreateCmd.Flags().StringSliceVar(&co.componentEnvVars, "env", []string{}, "Environmental variables for the component. For example --env VariableName=Value")
@@ -1076,7 +660,6 @@ func NewCmdCreate(name, fullName string) *cobra.Command {
componentCreateCmd.Flags().StringVar(&co.devfileMetadata.devfilePath.value, "devfile", "", "Path to the user specified devfile")
componentCreateCmd.Flags().StringVar(&co.devfileMetadata.token, "token", "", "Token to be used when downloading devfile from the devfile path that is specified via --devfile")
componentCreateCmd.Flags().StringVar(&co.devfileMetadata.starterToken, "starter-token", "", "Token to be used when downloading starter project")
componentCreateCmd.Flags().BoolVar(&co.forceS2i, "s2i", false, "Enforce S2I type components")
componentCreateCmd.SetUsageTemplate(odoutil.CmdUsageTemplate)
@@ -1091,11 +674,5 @@ func NewCmdCreate(name, fullName string) *cobra.Command {
completion.RegisterCommandFlagHandler(componentCreateCmd, "context", completion.FileCompletionHandler)
completion.RegisterCommandFlagHandler(componentCreateCmd, "binary", completion.FileCompletionHandler)
// Note: Remove these deprecation warnings once the S2I cleanup is done, see https://github.com/openshift/odo/issues/4932.
for _, flagName := range []string{"s2i", "git", "ref", "binary"} {
flag := componentCreateCmd.Flag(flagName)
flag.Deprecated = "support for the S2I components has been deprecated, consider creating a devfile component instead."
}
return componentCreateCmd
}

View File

@@ -5,43 +5,11 @@ import (
"github.com/devfile/library/pkg/devfile/parser"
parsercommon "github.com/devfile/library/pkg/devfile/parser/data/v2/common"
"github.com/openshift/odo/pkg/component"
"github.com/openshift/odo/pkg/config"
"github.com/openshift/odo/pkg/envinfo"
"github.com/openshift/odo/pkg/machineoutput"
"github.com/openshift/odo/pkg/odo/genericclioptions"
)
func (co *CreateOptions) SetComponentSettings(args []string) error {
err := co.setComponentSourceAttributes()
if err != nil {
return err
}
err = co.setComponentName(args)
if err != nil {
return err
}
var portList []string
if len(co.componentPorts) > 0 {
portList = co.componentPorts
} else {
portList, err = co.Client.GetPortsFromBuilderImage(*co.componentSettings.Type)
if err != nil {
return err
}
}
co.componentSettings.Ports = &(portList)
co.componentSettings.Project = &(co.Context.Project)
envs, err := config.NewEnvVarListFromSlice(co.componentEnvVars)
if err != nil {
return err
}
co.componentSettings.Envs = envs
co.ignores = []string{}
return nil
}
// decideAndDownloadStarterProject decides the starter project from the value passed by the user and
// downloads it
func decideAndDownloadStarterProject(devObj parser.DevfileObj, projectPassed string, token string, interactive bool, contextDir string) error {

View File

@@ -5,14 +5,11 @@ import (
"os"
"path/filepath"
"github.com/openshift/odo/pkg/envinfo"
"github.com/openshift/odo/pkg/util"
"github.com/spf13/cobra"
"k8s.io/klog"
"github.com/openshift/odo/pkg/component"
"github.com/openshift/odo/pkg/config"
"github.com/openshift/odo/pkg/devfile"
"github.com/openshift/odo/pkg/devfile/adapters/common"
@@ -54,16 +51,14 @@ type DeleteOptions struct {
componentForceDeleteFlag bool
componentDeleteAllFlag bool
componentDeleteWaitFlag bool
componentDeleteS2iFlag bool
componentContext string
isCmpExists bool
*ComponentOptions
// devfile path
devfilePath string
namespace string
show bool
EnvSpecificInfo *envinfo.EnvSpecificInfo
devfilePath string
namespace string
show bool
}
// NewDeleteOptions returns new instance of DeleteOptions
@@ -72,14 +67,12 @@ func NewDeleteOptions() *DeleteOptions {
componentForceDeleteFlag: false,
componentDeleteAllFlag: false,
componentDeleteWaitFlag: false,
componentDeleteS2iFlag: false,
componentContext: "",
isCmpExists: false,
ComponentOptions: &ComponentOptions{},
devfilePath: "",
namespace: "",
show: false,
EnvSpecificInfo: nil,
}
}
@@ -95,56 +88,19 @@ func (do *DeleteOptions) Complete(name string, cmd *cobra.Command, args []string
}
do.devfilePath = filepath.Join(do.componentContext, DevfilePath)
ConfigFilePath = filepath.Join(do.componentContext, configFile)
// if experimental mode is enabled and devfile is present
if !do.componentDeleteS2iFlag && util.CheckPathExists(do.devfilePath) {
do.EnvSpecificInfo, err = envinfo.NewEnvSpecificInfo(do.componentContext)
if err != nil {
return err
}
do.Context, err = genericclioptions.NewDevfileContext(cmd)
if err != nil {
return err
}
// The namespace was retrieved from the --project flag (or from the kube client if not set) and stored in kclient when initializing the context
do.namespace = do.KClient.Namespace
return nil
}
do.Context, err = genericclioptions.NewContext(cmd)
do.Context, err = genericclioptions.NewDevfileContext(cmd)
if err != nil {
return err
}
err = do.ComponentOptions.Complete(name, cmd, args)
// The namespace was retrieved from the --project flag (or from the kube client if not set) and stored in kclient when initializing the context
do.namespace = do.KClient.Namespace
return
return nil
}
// Validate validates the list parameters
func (do *DeleteOptions) Validate() (err error) {
// if experimental mode is enabled and devfile is present
if !do.componentDeleteS2iFlag && util.CheckPathExists(do.devfilePath) {
return nil
}
if do.Context.Project == "" || do.Application == "" {
return odoutil.ThrowContextError()
}
do.isCmpExists, err = component.Exists(do.Client, do.componentName, do.Application)
if err != nil {
return err
}
if !do.isCmpExists {
log.Errorf("Component %s does not exist on the cluster", do.ComponentOptions.componentName)
// If request is to delete non existing component without all flag, exit with exit code 1
if !do.componentDeleteAllFlag {
os.Exit(1)
}
}
return
}
@@ -153,59 +109,7 @@ func (do *DeleteOptions) Validate() (err error) {
func (do *DeleteOptions) Run(cmd *cobra.Command) (err error) {
klog.V(4).Infof("component delete called")
klog.V(4).Infof("args: %#v", do)
if !do.componentDeleteS2iFlag && util.CheckPathExists(do.devfilePath) {
return do.DevFileRun()
}
return do.s2iRun()
}
// s2iRun implements delete Run for s2i components
func (do *DeleteOptions) s2iRun() (err error) {
if do.isCmpExists {
err = printDeleteComponentInfo(do.Client, do.componentName, do.Context.Application, do.Context.Project)
if err != nil {
return err
}
if do.componentForceDeleteFlag || ui.Proceed(fmt.Sprintf("Are you sure you want to delete %v from %v?", do.componentName, do.Application)) {
err = component.Delete(do.Client, do.componentDeleteWaitFlag, do.componentName, do.Application)
if err != nil {
return err
}
log.Successf("Component %s from application %s has been deleted", do.componentName, do.Application)
} else {
return fmt.Errorf("Aborting deletion of component: %v", do.componentName)
}
}
if do.componentDeleteAllFlag {
if do.componentForceDeleteFlag || ui.Proceed(fmt.Sprintf("Are you sure you want to delete local config for %v?", do.componentName)) {
cfg, err := config.NewLocalConfigInfo(do.componentContext)
if err != nil {
return err
}
if err = util.DeleteIndexFile(do.componentContext); err != nil {
return err
}
// this checks if the config file exists or not
if err = cfg.DeleteConfigFile(); err != nil {
return err
}
if err = cfg.DeleteConfigDirIfEmpty(); err != nil {
return err
}
log.Successf("Config for the Component %s has been deleted", do.componentName)
} else {
return fmt.Errorf("Aborting deletion of config for component: %s", do.componentName)
}
}
return
return do.DevFileRun()
}
// DevFileRun has the logic to perform the required actions as part of command for devfiles
@@ -332,7 +236,6 @@ func NewCmdDelete(name, fullName string) *cobra.Command {
componentDeleteCmd.Flags().BoolVarP(&do.componentForceDeleteFlag, "force", "f", false, "Delete component without prompting")
componentDeleteCmd.Flags().BoolVarP(&do.componentDeleteAllFlag, "all", "a", false, "Delete component and local config")
componentDeleteCmd.Flags().BoolVarP(&do.componentDeleteWaitFlag, "wait", "w", false, "Wait for complete deletion of component and its dependent")
componentDeleteCmd.Flags().BoolVarP(&do.componentDeleteS2iFlag, "s2i", "", false, "Delete s2i component if devfile and s2i both component present with same name")
componentDeleteCmd.Flags().BoolVar(&do.show, "show-log", false, "If enabled, logs will be shown when deleted")

View File

@@ -8,8 +8,6 @@ import (
"github.com/openshift/odo/pkg/odo/genericclioptions"
odoutil "github.com/openshift/odo/pkg/odo/util"
"github.com/openshift/odo/pkg/odo/util/completion"
"github.com/openshift/odo/pkg/util"
"path/filepath"
"github.com/spf13/cobra"
@@ -62,19 +60,14 @@ Please provide a command to execute, odo exec -- <command to be execute>`)
eo.devfilePath = filepath.Join(eo.componentContext, devFile)
// If Devfile is present
if util.CheckPathExists(eo.devfilePath) {
eo.componentOptions.Context, err = genericclioptions.NewDevfileContext(cmd)
if err != nil {
return err
}
// The namespace was retrieved from the --project flag (or from the kube client if not set) and stored in kclient when initializing the context
eo.namespace = eo.componentOptions.KClient.Namespace
return nil
eo.componentOptions.Context, err = genericclioptions.NewDevfileContext(cmd)
if err != nil {
return err
}
// The namespace was retrieved from the --project flag (or from the kube client if not set) and stored in kclient when initializing the context
eo.namespace = eo.componentOptions.KClient.Namespace
// If Devfile does not exist, it is implied that we are running s2i
return fmt.Errorf("exec command does not work with s2i components")
return nil
}
// Validate validates the exec parameters

View File

@@ -1,145 +1,10 @@
package component
import (
"os"
devfilev1 "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
"github.com/openshift/odo/pkg/catalog"
"github.com/openshift/odo/pkg/config"
catalogutil "github.com/openshift/odo/pkg/odo/cli/catalog/util"
"github.com/openshift/odo/pkg/odo/cli/component/ui"
commonui "github.com/openshift/odo/pkg/odo/cli/ui"
"github.com/openshift/odo/pkg/util"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
"k8s.io/klog"
)
func (co *CreateOptions) SetComponentSettingsInteractively(catalogList catalog.ComponentTypeList) error {
componentTypeCandidates := catalogutil.FilterHiddenComponents(catalogList.Items)
selectedComponentType := ui.SelectComponentType(componentTypeCandidates)
selectedImageTag := ui.SelectImageTag(componentTypeCandidates, selectedComponentType)
componentType := selectedComponentType + ":" + selectedImageTag
co.componentSettings.Type = &componentType
// Ask for the type of source if not provided
selectedSourceType := ui.SelectSourceType([]config.SrcType{config.LOCAL, config.GIT, config.BINARY})
co.componentSettings.SourceType = &selectedSourceType
selectedSourcePath := LocalDirectoryDefaultLocation
// Get the current directory
currentDirectory, err := os.Getwd()
if err != nil {
return err
}
if selectedSourceType == config.BINARY {
// We ask for the source of the component context
co.componentContext = ui.EnterInputTypePath("context", currentDirectory, ".")
klog.V(4).Infof("Context: %s", co.componentContext)
// If it's a binary, we have to ask where the actual binary in relation
// to the context
selectedSourcePath = ui.EnterInputTypePath("binary", ".")
// Get the correct source location
sourceLocation, err := getSourceLocation(selectedSourcePath, co.componentContext)
if err != nil {
return errors.Wrapf(err, "unable to get source location")
}
co.componentSettings.SourceLocation = &sourceLocation
} else if selectedSourceType == config.GIT {
// For git, we ask for the Git URL and set that as the source location
cmpSrcLOC, selectedGitRef := ui.EnterGitInfo()
co.componentSettings.SourceLocation = &cmpSrcLOC
co.componentSettings.Ref = &selectedGitRef
} else if selectedSourceType == config.LOCAL {
// We ask for the source of the component, in this case the "path"!
co.componentContext = ui.EnterInputTypePath("path", currentDirectory, ".")
// Get the correct source location
if co.componentContext == "" {
co.componentContext = LocalDirectoryDefaultLocation
}
co.componentSettings.SourceLocation = &co.componentContext
}
defaultComponentName, err := createDefaultComponentName(co.Context, selectedComponentType, selectedSourceType, selectedSourcePath)
if err != nil {
return err
}
componentName := ui.EnterComponentName(defaultComponentName, co.Context)
appName := ui.EnterOpenshiftName(co.Context.Application, "Which application do you want the component to be associated with", co.Context)
co.componentSettings.Application = &appName
projectName := ui.EnterOpenshiftName(co.Context.Project, "Which project go you want the component to be created in", co.Context)
co.componentSettings.Project = &projectName
co.componentSettings.Name = &componentName
var ports []string
if commonui.Proceed("Do you wish to set advanced options") {
// if the user doesn't opt for advanced options, ports field would remain unpopulated
// we then set it at the end of this function
ports = ui.EnterPorts()
co.componentEnvVars = ui.EnterEnvVars()
if commonui.Proceed("Do you wish to set resource limits") {
memMax := ui.EnterMemory("maximum", "512Mi")
memMin := ui.EnterMemory("minimum", memMax)
cpuMax := ui.EnterCPU("maximum", "1")
cpuMin := ui.EnterCPU("minimum", cpuMax)
memoryQuantity, err := util.FetchResourceQuantity(corev1.ResourceMemory, memMin, memMax, "")
if err != nil {
return err
}
if memoryQuantity != nil {
co.componentSettings.MinMemory = &memMin
co.componentSettings.MaxMemory = &memMax
}
cpuQuantity, err := util.FetchResourceQuantity(corev1.ResourceCPU, cpuMin, cpuMax, "")
if err != nil {
return err
}
if cpuQuantity != nil {
co.componentSettings.MinCPU = &cpuMin
co.componentSettings.MaxCPU = &cpuMax
}
}
}
// if user didn't opt for advanced options, "ports" value remains empty which panics the "odo push"
// so we set the ports here
if len(ports) == 0 {
ports, err = co.Client.GetPortsFromBuilderImage(*co.componentSettings.Type)
if err != nil {
return err
}
}
co.componentSettings.Ports = &ports
co.componentSettings.Project = &(co.Context.Project)
envs, err := config.NewEnvVarListFromSlice(co.componentEnvVars)
if err != nil {
return err
}
co.componentSettings.Envs = envs
co.ignores = []string{}
// Above code is for INTERACTIVE mode
return nil
}
// getStarterProjectInteractiveMode gets starter project value by asking user in interactive mode.
func getStarterProjectInteractiveMode(projects []devfilev1.StarterProject) *devfilev1.StarterProject {
projectName := ui.SelectStarterProject(projects)

View File

@@ -2,20 +2,16 @@ package component
import (
"fmt"
"os"
"path/filepath"
"github.com/openshift/odo/pkg/odo/genericclioptions"
"github.com/openshift/odo/pkg/util"
appCmd "github.com/openshift/odo/pkg/odo/cli/application"
projectCmd "github.com/openshift/odo/pkg/odo/cli/project"
"github.com/openshift/odo/pkg/odo/genericclioptions"
"github.com/openshift/odo/pkg/odo/util/completion"
ktemplates "k8s.io/kubectl/pkg/util/templates"
odoutil "github.com/openshift/odo/pkg/odo/util"
"github.com/openshift/odo/pkg/component"
"github.com/spf13/cobra"
)
@@ -46,13 +42,8 @@ func (lo *LogOptions) Complete(name string, cmd *cobra.Command, args []string) (
lo.devfilePath = "devfile.yaml"
lo.devfilePath = filepath.Join(lo.componentContext, lo.devfilePath)
// if experimental mode is enabled and devfile is present
if util.CheckPathExists(lo.devfilePath) {
lo.ComponentOptions.Context, err = genericclioptions.NewDevfileContext(cmd)
return err
}
return lo.ComponentOptions.Complete(name, cmd, args)
lo.ComponentOptions.Context, err = genericclioptions.NewDevfileContext(cmd)
return err
}
// Validate validates the log parameters
@@ -62,15 +53,7 @@ func (lo *LogOptions) Validate() (err error) {
// Run has the logic to perform the required actions as part of command
func (lo *LogOptions) Run(cmd *cobra.Command) (err error) {
stdout := os.Stdout
// If experimental mode is enabled, use devfile push
if util.CheckPathExists(lo.devfilePath) {
err = lo.DevfileComponentLog()
} else {
// Retrieve the log
err = component.GetLogs(lo.Context.Client, lo.componentName, lo.Context.Application, lo.logFollow, stdout)
}
err = lo.DevfileComponentLog()
return
}

View File

@@ -2,10 +2,9 @@ package component
import (
"fmt"
"github.com/openshift/odo/pkg/component"
"path/filepath"
"github.com/openshift/odo/pkg/component"
"github.com/openshift/odo/pkg/log"
scontext "github.com/openshift/odo/pkg/segment/context"
"github.com/openshift/odo/pkg/devfile/validate"
@@ -91,138 +90,105 @@ func (po *PushOptions) Complete(name string, cmd *cobra.Command, args []string)
devfileExists := util.CheckPathExists(po.DevfilePath)
if !devfileExists {
// Note: Remove this deprecation warning once the S2I cleanup is done, see https://github.com/openshift/odo/issues/4932.
log.Deprecate(
"S2I components",
"Convert your existing S2I component to a Devfile component with `odo utils convert-to-devfile`, or consider re-creating with a Devfile component.",
)
return fmt.Errorf("the current direcotry doesn't contain a devfile")
}
if devfileExists {
po.Devfile, err = devfile.ParseFromFile(po.DevfilePath)
if err != nil {
return errors.Wrap(err, "unable to parse devfile")
}
err = validate.ValidateDevfileData(po.Devfile.Data)
if err != nil {
return err
}
// We retrieve the configuration information. If this does not exist, then BLANK is returned (important!).
envFileInfo, err := envinfo.NewEnvSpecificInfo(po.componentContext)
if err != nil {
return errors.Wrap(err, "unable to retrieve configuration information")
}
// If the file does not exist, we should populate the environment file with the correct env.yaml information
// such as name and namespace.
if !envFileInfo.Exists() {
klog.V(4).Info("Environment file does not exist, creating the env.yaml file in order to use 'odo push'")
// Since the environment file does not exist, we will retrieve a correct namespace from
// either cmd commands or the current default kubernetes namespace
namespace, err := retrieveCmdNamespace(cmd)
if err != nil {
return errors.Wrap(err, "unable to determine target namespace for the component")
}
client, err := genericclioptions.Client()
if err != nil {
return err
}
if err := checkDefaultProject(client, namespace); err != nil {
return err
}
// Retrieve a default name
// 1. Use args[0] if the user has supplied a name to be used
// 2. If the user did not provide a name, use gatherName to retrieve a name from the devfile.Metadata
// 3. Use the folder name that we are pushing from as a default name if none of the above exist
var name string
if len(args) == 1 {
name = args[0]
} else {
name, err = gatherName(po.Devfile, po.DevfilePath)
if err != nil {
return errors.Wrap(err, "unable to gather a name to apply to the env.yaml file")
}
}
// Create the environment file. This will actually *create* the env.yaml file in your context directory.
err = envFileInfo.SetComponentSettings(envinfo.ComponentSettings{Name: name, Project: namespace, AppName: "app"})
if err != nil {
return errors.Wrap(err, "failed to create env.yaml for devfile component")
}
} else if envFileInfo.GetNamespace() == "" {
// Since the project name doesn't exist in the environment file, we will retrieve a correct namespace from
// either cmd commands or the current default kubernetes namespace
// and write it to the env.yaml
namespace, err := retrieveCmdNamespace(cmd)
if err != nil {
return errors.Wrap(err, "unable to determine target namespace for devfile")
}
client, err := genericclioptions.Client()
if err != nil {
return err
}
if err := checkDefaultProject(client, namespace); err != nil {
return err
}
err = envFileInfo.SetConfiguration("project", namespace)
if err != nil {
return errors.Wrap(err, "failed to write the project to the env.yaml for devfile component")
}
} else if envFileInfo.GetNamespace() == "default" {
client, err := genericclioptions.Client()
if err != nil {
return err
}
if err := checkDefaultProject(client, envFileInfo.GetNamespace()); err != nil {
return err
}
}
if envFileInfo.GetApplication() == "" {
err = envFileInfo.SetConfiguration("app", "")
if err != nil {
return errors.Wrap(err, "failed to write the app to the env.yaml for devfile component")
}
}
po.EnvSpecificInfo = envFileInfo
po.Context, err = genericclioptions.NewDevfileContext(cmd)
if err != nil {
return err
}
return nil
po.Devfile, err = devfile.ParseFromFile(po.DevfilePath)
if err != nil {
return errors.Wrap(err, "unable to parse devfile")
}
// Set the correct context, which also sets the LocalConfigInfo
po.Context, err = genericclioptions.NewContextCreatingAppIfNeeded(cmd)
err = validate.ValidateDevfileData(po.Devfile.Data)
if err != nil {
return err
}
err = po.SetSourceInfo()
// We retrieve the configuration information. If this does not exist, then BLANK is returned (important!).
envFileInfo, err := envinfo.NewEnvSpecificInfo(po.componentContext)
if err != nil {
return errors.Wrap(err, "unable to set source information")
return errors.Wrap(err, "unable to retrieve configuration information")
}
// Apply ignore information
err = genericclioptions.ApplyIgnore(&po.ignores, po.sourcePath)
if err != nil {
return errors.Wrap(err, "unable to apply ignore information")
// If the file does not exist, we should populate the environment file with the correct env.yaml information
// such as name and namespace.
if !envFileInfo.Exists() {
klog.V(4).Info("Environment file does not exist, creating the env.yaml file in order to use 'odo push'")
// Since the environment file does not exist, we will retrieve a correct namespace from
// either cmd commands or the current default kubernetes namespace
namespace, err := retrieveCmdNamespace(cmd)
if err != nil {
return errors.Wrap(err, "unable to determine target namespace for the component")
}
client, err := genericclioptions.Client()
if err != nil {
return err
}
if err := checkDefaultProject(client, namespace); err != nil {
return err
}
// Retrieve a default name
// 1. Use args[0] if the user has supplied a name to be used
// 2. If the user did not provide a name, use gatherName to retrieve a name from the devfile.Metadata
// 3. Use the folder name that we are pushing from as a default name if none of the above exist
var name string
if len(args) == 1 {
name = args[0]
} else {
name, err = gatherName(po.Devfile, po.DevfilePath)
if err != nil {
return errors.Wrap(err, "unable to gather a name to apply to the env.yaml file")
}
}
// Create the environment file. This will actually *create* the env.yaml file in your context directory.
err = envFileInfo.SetComponentSettings(envinfo.ComponentSettings{Name: name, Project: namespace, AppName: "app"})
if err != nil {
return errors.Wrap(err, "failed to create env.yaml for devfile component")
}
} else if envFileInfo.GetNamespace() == "" {
// Since the project name doesn't exist in the environment file, we will retrieve a correct namespace from
// either cmd commands or the current default kubernetes namespace
// and write it to the env.yaml
namespace, err := retrieveCmdNamespace(cmd)
if err != nil {
return errors.Wrap(err, "unable to determine target namespace for devfile")
}
client, err := genericclioptions.Client()
if err != nil {
return err
}
if err := checkDefaultProject(client, namespace); err != nil {
return err
}
err = envFileInfo.SetConfiguration("project", namespace)
if err != nil {
return errors.Wrap(err, "failed to write the project to the env.yaml for devfile component")
}
} else if envFileInfo.GetNamespace() == "default" {
client, err := genericclioptions.Client()
if err != nil {
return err
}
if err := checkDefaultProject(client, envFileInfo.GetNamespace()); err != nil {
return err
}
}
// Get the project information and resolve it.
prjName := po.LocalConfigInfo.GetProject()
po.ResolveSrcAndConfigFlags()
err = po.ResolveProject(prjName)
if envFileInfo.GetApplication() == "" {
err = envFileInfo.SetConfiguration("app", "")
if err != nil {
return errors.Wrap(err, "failed to write the app to the env.yaml for devfile component")
}
}
po.EnvSpecificInfo = envFileInfo
po.Context, err = genericclioptions.NewDevfileContext(cmd)
if err != nil {
return err
}
@@ -232,36 +198,6 @@ func (po *PushOptions) Complete(name string, cmd *cobra.Command, args []string)
// Validate validates the push parameters
func (po *PushOptions) Validate() (err error) {
// If Devfile is present we do not need to validate the below S2I checks
// TODO: Perhaps one day move Devfile validation to here instead?
if util.CheckPathExists(po.DevfilePath) {
return nil
}
// Validation for S2i components
log.Info("Validation")
// First off, we check to see if the component exists. This is ran each time we do `odo push`
s := log.Spinner("Checking component")
defer s.End(false)
po.doesComponentExist, err = component.Exists(po.Context.Client, po.LocalConfigInfo.GetName(), po.LocalConfigInfo.GetApplication())
if err != nil {
return errors.Wrapf(err, "failed to check if component of name %s exists in application %s", po.LocalConfigInfo.GetName(), po.LocalConfigInfo.GetApplication())
}
if err = component.ValidateComponentCreateRequest(po.Context.Client, po.LocalConfigInfo.GetComponentSettings(), po.componentContext); err != nil {
s.End(false)
log.Italic("\nRun 'odo catalog list components' for a list of supported component types")
return fmt.Errorf("Invalid component type %s, %v", *po.LocalConfigInfo.GetComponentSettings().Type, errors.Cause(err))
}
if !po.doesComponentExist && po.pushSource && !po.pushConfig {
return fmt.Errorf("Component %s does not exist and hence cannot push only source. Please use `odo push` without any flags or with both `--source` and `--config` flags", po.LocalConfigInfo.GetName())
}
s.End(true)
return nil
}
@@ -270,20 +206,12 @@ func (po *PushOptions) Run(cmd *cobra.Command) (err error) {
if scontext.GetTelemetryStatus(cmd.Context()) {
scontext.SetClusterType(cmd.Context(), po.Client)
}
// If experimental mode is enabled, use devfile push
if util.CheckPathExists(po.DevfilePath) {
if scontext.GetTelemetryStatus(cmd.Context()) {
scontext.SetComponentType(cmd.Context(), component.GetComponentTypeFromDevfileMetadata(po.Devfile.Data.GetMetadata()))
}
// Return Devfile push
return po.DevfilePush()
}
// Legacy odo push
if scontext.GetTelemetryStatus(cmd.Context()) {
scontext.SetComponentType(cmd.Context(), po.LocalConfigInfo.GetType())
scontext.SetComponentType(cmd.Context(), component.GetComponentTypeFromDevfileMetadata(po.Devfile.Data.GetMetadata()))
}
return po.Push()
// Return Devfile push
return po.DevfilePush()
}
// NewCmdPush implements the push odo command

View File

@@ -1,236 +0,0 @@
package component
import (
"fmt"
"os"
"path/filepath"
"strings"
"github.com/fatih/color"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/openshift/odo/pkg/component"
"github.com/openshift/odo/pkg/config"
"github.com/openshift/odo/pkg/log"
appCmd "github.com/openshift/odo/pkg/odo/cli/application"
projectCmd "github.com/openshift/odo/pkg/odo/cli/project"
"github.com/openshift/odo/pkg/odo/genericclioptions"
odoutil "github.com/openshift/odo/pkg/odo/util"
"github.com/openshift/odo/pkg/odo/util/completion"
"github.com/openshift/odo/pkg/util"
ktemplates "k8s.io/kubectl/pkg/util/templates"
)
// UpdateRecommendedCommandName is the recommended update command name
const UpdateRecommendedCommandName = "update"
// UpdateOptions encapsulates the update command options
type UpdateOptions struct {
binary string
git string
local string
ref string
*CommonPushOptions
// devfile path
devfilePath string
}
var updateCmdExample = ktemplates.Examples(` # Change the source code path of currently active component to local with source in ./frontend directory
%[1]s --local ./frontend
# Change the source code path of currently active component to git
%[1]s --git https://github.com/openshift/nodejs-ex.git
# Change the source code path of of currently active component to a binary named sample.war in ./downloads directory
%[1]s --binary ./downloads/sample.war
`)
const (
descDeprecationWarning = "WARNING: 'odo update' command will be removed in the future odo version."
deprecationWarning = `WARNING: 'odo update' command will be removed in the future odo version.
You should be using 'odo config' command instead.
example:
odo config set SourceType git
odo config set SourceLocation https://github.com/example/example`
)
const devfileErrorString string = "'odo update' command is not available for Devfile based components."
// NewUpdateOptions returns new instance of UpdateOptions
func NewUpdateOptions() *UpdateOptions {
return &UpdateOptions{
CommonPushOptions: &CommonPushOptions{
pushConfig: true, // we push everything
forceBuild: true,
pushSource: true,
show: false,
}}
}
// Complete completes update args
func (uo *UpdateOptions) Complete(name string, cmd *cobra.Command, args []string) (err error) {
uo.devfilePath = filepath.Join(uo.componentContext, DevfilePath)
if util.CheckPathExists(uo.devfilePath) {
// Configure the devfile context
uo.Context, err = genericclioptions.NewDevfileContext(cmd)
return
}
uo.Context, err = genericclioptions.NewContext(cmd)
if err != nil {
return err
}
uo.LocalConfigInfo, err = config.NewLocalConfigInfo(uo.componentContext)
if err != nil {
return errors.Wrapf(err, "failed to update component")
}
return
}
// Validate validates the update parameters
func (uo *UpdateOptions) Validate() (err error) {
// if experimental mode is enabled and devfile is present
if util.CheckPathExists(uo.devfilePath) {
return nil
}
uo.doesComponentExist, err = component.Exists(uo.Context.Client, uo.LocalConfigInfo.GetName(), uo.LocalConfigInfo.GetApplication())
if err != nil {
return errors.Wrapf(err, "failed to check if component of name %s exists in application %s", uo.LocalConfigInfo.GetName(), uo.LocalConfigInfo.GetApplication())
}
checkFlag := 0
if len(uo.binary) != 0 {
checkFlag++
uo.sourceType = config.BINARY
uo.sourcePath = uo.binary
if strings.HasPrefix(uo.sourcePath, fmt.Sprintf("..%c", filepath.Separator)) {
return fmt.Errorf("%s binary needs to be inside of the context directory", uo.sourcePath)
}
}
if len(uo.git) != 0 {
checkFlag++
uo.sourceType = config.GIT
uo.sourcePath = uo.git
}
if len(uo.local) != 0 {
checkFlag++
uo.sourceType = config.LOCAL
uo.sourcePath = uo.local
srcLocInfo, err := os.Stat(uo.sourcePath)
if err != nil {
return fmt.Errorf("error while validating source path: %v", err.Error())
}
if !srcLocInfo.IsDir() {
return fmt.Errorf("source path for component created for local source needs to be a directory")
}
}
if len(uo.componentContext) == 0 {
dir, err := os.Getwd()
if err != nil {
return errors.Wrapf(err, "failed to update component %s", uo.LocalConfigInfo.GetName())
}
uo.componentContext = dir
}
fileInfo, err := os.Stat(uo.componentContext)
if err != nil {
return err
}
if !fileInfo.IsDir() {
return fmt.Errorf("Please provide a path to the directory as --context")
}
if checkFlag != 1 {
return fmt.Errorf("The source can be either --binary or --local or --git")
}
// if --git is not specified but --ref is still given then error has to be thrown
if len(uo.git) == 0 && len(uo.ref) != 0 {
return fmt.Errorf("The --ref flag is only valid for --git flag")
}
if len(uo.Context.Application) == 0 {
return fmt.Errorf("Cannot update as no application is set as active")
}
return
}
// Run has the logic to perform the required actions as part of command
func (uo *UpdateOptions) Run(cmd *cobra.Command) (err error) {
// if devfile is present
if util.CheckPathExists(uo.devfilePath) {
return errors.New(devfileErrorString)
}
yellow := color.New(color.FgYellow).SprintFunc()
log.Warning(yellow(deprecationWarning))
compSettings := uo.LocalConfigInfo.GetComponentSettings()
compSettings.SourceLocation = &uo.sourcePath
compSettings.SourceType = &uo.sourceType
if len(uo.ref) != 0 {
compSettings.Ref = &uo.ref
}
err = uo.LocalConfigInfo.SetComponentSettings(compSettings)
if err != nil {
return err
}
if err = uo.Push(); err != nil {
return errors.Wrap(err, "error while updating")
}
cmpName := uo.LocalConfigInfo.GetName()
log.Successf("The component %s was updated successfully", cmpName)
return
}
// NewCmdUpdate implements the Update odo command
func NewCmdUpdate(name, fullName string) *cobra.Command {
uo := NewUpdateOptions()
var updateCmd = &cobra.Command{
Use: name,
Args: cobra.MaximumNArgs(0),
Short: "Update the source code path of a component",
Long: fmt.Sprint("Update the source code path of a component\n", descDeprecationWarning),
Example: fmt.Sprintf(updateCmdExample, fullName),
Run: func(cmd *cobra.Command, args []string) {
genericclioptions.GenericRun(uo, cmd, args)
},
}
genericclioptions.AddContextFlag(updateCmd, &uo.componentContext)
updateCmd.Flags().BoolVar(&uo.show, "show-log", false, "If enabled, logs will be shown when built")
updateCmd.Flags().StringVarP(&uo.git, "git", "g", "", "git source")
updateCmd.Flags().StringVarP(&uo.local, "local", "l", "", "Use local directory as a source for component.")
updateCmd.Flags().StringVarP(&uo.ref, "ref", "r", "", "Use a specific ref e.g. commit, branch or tag of the git repository")
updateCmd.Annotations = map[string]string{"command": "component"}
updateCmd.SetUsageTemplate(odoutil.CmdUsageTemplate)
//Adding `--application` flag
appCmd.AddApplicationFlag(updateCmd)
//Adding `--project` flag
projectCmd.AddProjectFlag(updateCmd)
completion.RegisterCommandFlagHandler(updateCmd, "local", completion.FileCompletionHandler)
completion.RegisterCommandFlagHandler(updateCmd, "binary", completion.FileCompletionHandler)
completion.RegisterCommandHandler(updateCmd, completion.ComponentNameCompletionHandler)
return updateCmd
}

View File

@@ -6,13 +6,11 @@ import (
"path/filepath"
"strings"
"github.com/openshift/odo/pkg/config"
"github.com/openshift/odo/pkg/devfile"
"github.com/openshift/odo/pkg/devfile/adapters"
"github.com/openshift/odo/pkg/devfile/adapters/common"
"github.com/openshift/odo/pkg/devfile/adapters/kubernetes"
"github.com/openshift/odo/pkg/envinfo"
"github.com/openshift/odo/pkg/occlient"
appCmd "github.com/openshift/odo/pkg/odo/cli/application"
projectCmd "github.com/openshift/odo/pkg/odo/cli/project"
"github.com/pkg/errors"
@@ -21,7 +19,6 @@ import (
"github.com/openshift/odo/pkg/odo/genericclioptions"
"k8s.io/klog"
"github.com/openshift/odo/pkg/component"
odoutil "github.com/openshift/odo/pkg/odo/util"
"github.com/openshift/odo/pkg/util"
"github.com/openshift/odo/pkg/watch"
@@ -45,10 +42,8 @@ type WatchOptions struct {
delay int
show bool
sourceType config.SrcType
sourcePath string
componentContext string
client *occlient.Client
componentName string
devfilePath string
@@ -75,62 +70,14 @@ func NewWatchOptions() *WatchOptions {
func (wo *WatchOptions) Complete(name string, cmd *cobra.Command, args []string) (err error) {
wo.devfilePath = filepath.Join(wo.componentContext, DevfilePath)
// if experimental mode is enabled and devfile is present
if util.CheckPathExists(wo.devfilePath) {
wo.Context, err = genericclioptions.NewDevfileContext(cmd)
if err != nil {
return err
}
// Set the source path to either the context or current working directory (if context not set)
wo.sourcePath, err = util.GetAbsPath(wo.componentContext)
if err != nil {
return errors.Wrap(err, "unable to get source path")
}
// Apply ignore information
err = genericclioptions.ApplyIgnore(&wo.ignores, wo.sourcePath)
if err != nil {
return errors.Wrap(err, "unable to apply ignore information")
}
// Get the component name
wo.componentName = wo.EnvSpecificInfo.GetName()
// Parse devfile and validate
devObj, err := devfile.ParseFromFile(wo.devfilePath)
if err != nil {
return err
}
var platformContext interface{}
// The namespace was retrieved from the --project flag (or from the kube client if not set) and stored in kclient when initializing the context
wo.namespace = wo.KClient.Namespace
platformContext = kubernetes.KubernetesContext{
Namespace: wo.namespace,
}
wo.initialDevfileHandler, err = adapters.NewComponentAdapter(wo.componentName, wo.componentContext, wo.Application, devObj, platformContext)
return err
}
// Set the correct context
wo.Context, err = genericclioptions.NewContextCreatingAppIfNeeded(cmd)
wo.Context, err = genericclioptions.NewDevfileContext(cmd)
if err != nil {
return err
}
wo.client, err = genericclioptions.Client()
// Set the source path to either the context or current working directory (if context not set)
wo.sourcePath, err = util.GetAbsPath(wo.componentContext)
if err != nil {
return err
}
// Set the necessary values within WatchOptions
conf := wo.Context.LocalConfigInfo
wo.sourceType = conf.LocalConfig.GetSourceType()
// Get SourceLocation here...
wo.sourcePath, err = conf.GetOSSourcePath()
if err != nil {
return errors.Wrap(err, "unable to retrieve absolute path to source location")
return errors.Wrap(err, "unable to get source path")
}
// Apply ignore information
@@ -139,7 +86,25 @@ func (wo *WatchOptions) Complete(name string, cmd *cobra.Command, args []string)
return errors.Wrap(err, "unable to apply ignore information")
}
return
// Get the component name
wo.componentName = wo.EnvSpecificInfo.GetName()
// Parse devfile and validate
devObj, err := devfile.ParseFromFile(wo.devfilePath)
if err != nil {
return err
}
var platformContext interface{}
// The namespace was retrieved from the --project flag (or from the kube client if not set) and stored in kclient when initializing the context
wo.namespace = wo.KClient.Namespace
platformContext = kubernetes.KubernetesContext{
Namespace: wo.namespace,
}
wo.initialDevfileHandler, err = adapters.NewComponentAdapter(wo.componentName, wo.componentContext, wo.Application, devObj, platformContext)
return err
}
// Validate validates the watch parameters
@@ -154,98 +119,43 @@ func (wo *WatchOptions) Validate() (err error) {
klog.V(4).Infof("delay=0 means changes will be pushed as soon as they are detected which can cause performance issues")
}
// if experimental mode is enabled and devfile is present, return. The rest of the validation is for non-devfile components
if util.CheckPathExists(wo.devfilePath) {
if wo.devfileDebugCommand != "" && wo.EnvSpecificInfo != nil && wo.EnvSpecificInfo.GetRunMode() != envinfo.Debug {
return fmt.Errorf("please start the component in debug mode using `odo push --debug` to use the --debug-command flag")
}
exists, err := wo.initialDevfileHandler.DoesComponentExist(wo.componentName, wo.Application)
if err != nil {
return err
}
if !exists {
return fmt.Errorf("component does not exist. Please use `odo push` to create your component")
}
return nil
if wo.devfileDebugCommand != "" && wo.EnvSpecificInfo != nil && wo.EnvSpecificInfo.GetRunMode() != envinfo.Debug {
return fmt.Errorf("please start the component in debug mode using `odo push --debug` to use the --debug-command flag")
}
// Validate source of component is either local source or binary path until git watch is supported
if wo.sourceType != "binary" && wo.sourceType != "local" {
return fmt.Errorf("Watch is supported by binary and local components only and source type of component %s is %s",
wo.LocalConfigInfo.GetName(),
wo.sourceType)
}
// Validate component path existence and accessibility permissions for odo
if _, err := os.Stat(wo.sourcePath); err != nil {
return errors.Wrapf(err, "Cannot watch %s", wo.sourcePath)
}
cmpName := wo.LocalConfigInfo.GetName()
appName := wo.LocalConfigInfo.GetApplication()
if len(wo.Application) != 0 {
appName = wo.Application
}
exists, err := component.Exists(wo.Client, cmpName, appName)
exists, err := wo.initialDevfileHandler.DoesComponentExist(wo.componentName, wo.Application)
if err != nil {
return
return err
}
if !exists {
return fmt.Errorf("component does not exist. Please use `odo push` to create your component")
}
return
return nil
}
// Run has the logic to perform the required actions as part of command
func (wo *WatchOptions) Run(cmd *cobra.Command) (err error) {
// if experimental mode is enabled and devfile is present
if util.CheckPathExists(wo.devfilePath) {
err = watch.DevfileWatchAndPush(
os.Stdout,
watch.WatchParameters{
ComponentName: wo.componentName,
ApplicationName: wo.Context.Application,
Path: wo.sourcePath,
FileIgnores: util.GetAbsGlobExps(wo.sourcePath, wo.ignores),
PushDiffDelay: wo.delay,
StartChan: nil,
ExtChan: make(chan bool),
DevfileWatchHandler: wo.regenerateAdapterAndPush,
Show: wo.show,
DevfileBuildCmd: strings.ToLower(wo.devfileBuildCommand),
DevfileRunCmd: strings.ToLower(wo.devfileRunCommand),
DevfileDebugCmd: strings.ToLower(wo.devfileDebugCommand),
EnvSpecificInfo: wo.EnvSpecificInfo,
},
)
if err != nil {
return errors.Wrapf(err, "Error while trying to watch %s", wo.sourcePath)
}
return err
}
err = watch.WatchAndPush(
wo.Context.Client,
err = watch.DevfileWatchAndPush(
os.Stdout,
watch.WatchParameters{
ComponentName: wo.LocalConfigInfo.GetName(),
ComponentName: wo.componentName,
ApplicationName: wo.Context.Application,
Path: wo.sourcePath,
FileIgnores: util.GetAbsGlobExps(wo.sourcePath, wo.ignores),
PushDiffDelay: wo.delay,
StartChan: nil,
ExtChan: make(chan bool),
DevfileWatchHandler: nil,
WatchHandler: component.PushLocal,
DevfileWatchHandler: wo.regenerateAdapterAndPush,
Show: wo.show,
DevfileBuildCmd: strings.ToLower(wo.devfileBuildCommand),
DevfileRunCmd: strings.ToLower(wo.devfileRunCommand),
DevfileDebugCmd: strings.ToLower(wo.devfileDebugCommand),
EnvSpecificInfo: wo.EnvSpecificInfo,
},
)
if err != nil {
return errors.Wrapf(err, "Error while trying to watch %s", wo.sourcePath)
}
return
return err
}
// NewCmdWatch implements the watch odo command

View File

@@ -2,16 +2,12 @@ package utils
import (
"fmt"
"path/filepath"
"github.com/fatih/color"
"github.com/openshift/odo/pkg/config"
"github.com/openshift/odo/pkg/devfile/convert"
"github.com/openshift/odo/pkg/log"
"github.com/openshift/odo/pkg/odo/cli/component"
"github.com/openshift/odo/pkg/odo/genericclioptions"
"github.com/openshift/odo/pkg/util"
"github.com/pkg/errors"
"github.com/spf13/cobra"
ktemplates "k8s.io/kubectl/pkg/util/templates"
@@ -69,11 +65,6 @@ func NewConvertOptions() *ConvertOptions {
// Complete completes ConvertOptions after they've been created
func (co *ConvertOptions) Complete(name string, cmd *cobra.Command, args []string) (err error) {
if !util.CheckPathExists(filepath.Join(co.componentContext, component.ConfigFilePath)) {
return errors.New("this directory does not contain an odo s2i component, Please run the command from odo component directory to convert s2i component to devfile")
}
co.context, err = genericclioptions.NewContext(cmd)
if err != nil {
return err

View File

@@ -37,7 +37,7 @@ func getValidEnvInfo(command *cobra.Command) (*envinfo.EnvSpecificInfo, error) {
// Check to see if the environment file exists
if !envInfo.Exists() {
return nil, fmt.Errorf("The current directory does not represent an odo component. Use 'odo create' to create component here or switch to directory with a component")
return nil, fmt.Errorf("the current directory does not represent an odo component. Use 'odo create' to create component here or switch to directory with a component")
}
return envInfo, nil
@@ -69,7 +69,7 @@ func getValidConfig(command *cobra.Command, ignoreMissingConfiguration bool) (*c
if !localConfiguration.Exists() && ignoreMissingConfiguration {
klog.V(4).Info("There is NO config file that exists, we are however ignoring this as the ignoreMissingConfiguration flag has been passed in as true")
} else if !localConfiguration.Exists() {
return nil, fmt.Errorf("The current directory does not represent an odo component. Use 'odo create' to create component here or switch to directory with a component")
return nil, fmt.Errorf("the current directory does not represent an odo component. Use 'odo create' to create component here or switch to directory with a component")
}
// else simply return the local config info

View File

@@ -46,10 +46,6 @@ case ${1} in
make test-integration-devfile
shout "| Executing on minishift: core beta, java, source e2e tests"
make test-e2e-beta
make test-e2e-java
make test-e2e-source
make test-e2e-images
make test-e2e-devfile
odo logout

View File

@@ -1,160 +0,0 @@
// This test file verifies all the supported container images listed in the
// file https://github.com/openshift/odo-init-image/blob/master/language-scripts/image-mappings.json
package e2escenarios
import (
"os"
"path/filepath"
"runtime"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/openshift/odo/pkg/devfile/convert"
"github.com/openshift/odo/pkg/util"
"github.com/openshift/odo/tests/helper"
"github.com/openshift/odo/tests/integration/devfile/utils"
)
var _ = Describe("odo supported images e2e tests", func() {
var oc helper.OcRunner
var commonVar helper.CommonVar
appName := "app"
// This is run before every Spec (It)
var _ = BeforeEach(func() {
// initialize oc runner
oc = helper.NewOcRunner("oc")
commonVar = helper.CommonBeforeEach()
oc.AddSecret(commonVar)
})
// Clean up after the test
// This is run after every Spec (It)
var _ = AfterEach(func() {
helper.CommonAfterEach(commonVar)
})
// verifySupportedImage takes arguments supported images, source type, image type, namespace and application name.
// Also verify the flow of odo commands with respect to supported images only.
verifySupportedImage := func(image, srcType, cmpType, project, appName, context string) {
cmpName := srcType + "-app"
// create the component
helper.CopyExample(filepath.Join("source", srcType), commonVar.Context)
helper.Cmd("odo", "create", "--s2i", cmpType, cmpName, "--project", project, "--context", context, "--app", appName).ShouldPass()
// push component and validate
helper.Cmd("odo", "push", "--context", context).ShouldPass()
cmpList := helper.Cmd("odo", "list", "--context", context).ShouldPass().Out()
Expect(cmpList).To(ContainSubstring(srcType + "-app"))
// push again just to confirm it works
helper.Cmd("odo", "push", "--context", context).ShouldPass()
// get the url
routeURL := helper.DetermineRouteURL(context)
// Ping said URL
helper.HttpWaitFor(routeURL, "Hello", 90, 1)
// edit source and validate
if srcType == "openjdk" {
helper.ReplaceString(filepath.Join(context, "src", "main", "java", "MessageProducer.java"), "Hello", "Hello Java UPDATED")
helper.Cmd("odo", "push", "--context", context).ShouldPass()
helper.HttpWaitFor(routeURL, "Hello Java UPDATED", 90, 1)
} else {
helper.ReplaceString(filepath.Join(context, "server.js"), "Hello", "Hello nodejs UPDATED")
helper.Cmd("odo", "push", "--context", context).ShouldPass()
helper.HttpWaitFor(routeURL, "Hello nodejs UPDATED", 90, 1)
}
watchFlag := ""
// odo watch and validate
utils.OdoWatch(utils.OdoV1Watch{},
utils.OdoV2Watch{
CmpName: cmpName,
StringsToBeMatched: []string{"Executing s2i-assemble command", "Executing s2i-run command"},
FolderToCheck: convert.DefaultSourceMappingS2i,
SrcType: srcType,
}, project, context, watchFlag, oc, "kube")
// delete the component and validate
helper.Cmd("odo", "app", "delete", "app", "--project", project, "-f").ShouldPass()
cmpLst := helper.Cmd("odo", "list", "--context", context).ShouldPass().Out()
Expect(cmpLst).To(ContainSubstring("Not Pushed"))
}
Context("odo supported images deployment on amd64", func() {
JustBeforeEach(func() {
if runtime.GOARCH != "amd64" {
Skip("Skipping test because these images are not supported.")
}
})
It("Should be able to verify the nodejs-10 image", func() {
oc.ImportImageFromRegistry("registry.access.redhat.com", "rhoar-nodejs/nodejs-10:latest", "nodejs:latest", commonVar.Project)
verifySupportedImage("rhoar-nodejs/nodejs-10:latest", "nodejs", "nodejs:latest", commonVar.Project, appName, commonVar.Context)
})
It("Should be able to verify the nodejs-10-centos7 image", func() {
oc.ImportImageFromRegistry("quay.io", "centos7/nodejs-10-centos7:latest", "nodejs:latest", commonVar.Project)
verifySupportedImage("centos7/nodejs-10-centos7:latest", "nodejs", "nodejs:latest", commonVar.Project, appName, commonVar.Context)
})
It("Should be able to verify the nodejs-12-centos7 image", func() {
oc.ImportImageFromRegistry("quay.io", "centos7/nodejs-12-centos7:latest", "nodejs:latest", commonVar.Project)
verifySupportedImage("centos7/nodejs-12-centos7:latest", "nodejs", "nodejs:latest", commonVar.Project, appName, commonVar.Context)
})
})
Context("odo supported images deployment", func() {
It("Should be able to verify the openjdk18-openshift image", func() {
oc.ImportImageFromRegistry("registry.access.redhat.com", "redhat-openjdk-18/openjdk18-openshift:latest", "java:8", commonVar.Project)
verifySupportedImage("redhat-openjdk-18/openjdk18-openshift:latest", "openjdk", "java:8", commonVar.Project, appName, commonVar.Context)
})
It("Should be able to verify the nodejs-10-rhel7 image", func() {
oc.ImportImageFromRegistry("registry.access.redhat.com", "rhscl/nodejs-10-rhel7:latest", "nodejs:latest", commonVar.Project)
verifySupportedImage("rhscl/nodejs-10-rhel7:latest", "nodejs", "nodejs:latest", commonVar.Project, appName, commonVar.Context)
})
})
Context("odo supported private registry images deployment", func() {
JustBeforeEach(func() {
// Issue for configuring login secret for travis CI https://github.com/openshift/odo/issues/3640
if os.Getenv("CI") != "openshift" {
Skip("Skipping it on travis CI, skipping")
}
})
It("Should be able to verify the nodejs-12 image", func() {
redhatNodejs12UBI8Project := util.GetEnvWithDefault("REDHAT_NODEJS12_UBI8_PROJECT", "nodejs-12")
oc.ImportImageFromRegistry("registry.redhat.io", "ubi8/nodejs-12:latest", "nodejs:latest", redhatNodejs12UBI8Project)
verifySupportedImage("ubi8/nodejs-12:latest", "nodejs", "nodejs:latest", redhatNodejs12UBI8Project, appName, commonVar.Context)
})
It("Should be able to verify the nodejs-12-rhel7 image", func() {
redhatNodejs12RHEL7Project := util.GetEnvWithDefault("REDHAT_NODEJS12_RHEL7_PROJECT", "nodejs-12-rhel7")
oc.ImportImageFromRegistry("registry.redhat.io", "rhscl/nodejs-12-rhel7:latest", "nodejs:latest", redhatNodejs12RHEL7Project)
verifySupportedImage("rhscl/nodejs-12-rhel7:latest", "nodejs", "nodejs:latest", redhatNodejs12RHEL7Project, appName, commonVar.Context)
})
It("Should be able to verify the openjdk-11 image", func() {
redhatOpenjdk11UBI8Project := util.GetEnvWithDefault("REDHAT_OPENJDK11_UBI8_PROJECT", "openjdk-11")
oc.ImportImageFromRegistry("registry.redhat.io", "ubi8/openjdk-11:latest", "java:8", redhatOpenjdk11UBI8Project)
verifySupportedImage("ubi8/openjdk-11:latest", "openjdk", "java:8", redhatOpenjdk11UBI8Project, appName, commonVar.Context)
})
It("Should be able to verify the openjdk-11-rhel8 image", func() {
redhatOpenjdk12RHEL8Project := util.GetEnvWithDefault("REDHAT_OPENJDK11_RHEL8_PROJECT", "openjdk-11-rhel8")
oc.ImportImageFromRegistry("registry.redhat.io", "openjdk/openjdk-11-rhel8:latest", "java:8", redhatOpenjdk12RHEL8Project)
verifySupportedImage("openjdk/openjdk-11-rhel8:latest", "openjdk", "java:8", redhatOpenjdk12RHEL8Project, appName, commonVar.Context)
})
It("Should be able to verify the nodejs-14 image", func() {
redhatNodeJS14UBI8Project := util.GetEnvWithDefault("REDHAT_NODEJS14_UBI8_PROJECT", "nodejs-14")
oc.ImportImageFromRegistry("registry.redhat.io", "ubi8/nodejs-14:latest", "nodejs:latest", redhatNodeJS14UBI8Project)
verifySupportedImage("ubi8/nodejs-14:latest", "nodejs", "nodejs:latest", redhatNodeJS14UBI8Project, appName, commonVar.Context)
})
})
})

View File

@@ -1,117 +0,0 @@
package e2escenarios
import (
"path/filepath"
"runtime"
. "github.com/onsi/ginkgo"
"github.com/openshift/odo/tests/helper"
)
var _ = Describe("odo java e2e tests", func() {
var oc helper.OcRunner
var commonVar helper.CommonVar
// contains a minimal javaee app
const warGitRepo = "https://github.com/lordofthejars/book-insultapp"
// contains a minimal javalin app
const jarGitRepo = "https://github.com/geoand/javalin-helloworld"
// This is run before every Spec (It)
var _ = BeforeEach(func() {
// initialize oc runner
oc = helper.NewOcRunner("oc")
commonVar = helper.CommonBeforeEach()
oc.AddSecret(commonVar)
})
// Clean up after the test
// This is run after every Spec (It)
var _ = AfterEach(func() {
helper.CommonAfterEach(commonVar)
})
// Test wildfly
Context("odo wildfly component creation ", func() {
JustBeforeEach(func() {
if runtime.GOARCH == "s390x" || runtime.GOARCH == "ppc64le" {
Skip("Skipping test because there is no supported wildfly builder image.")
}
})
It("Should be able to deploy a git repo that contains a wildfly application without wait flag", func() {
helper.Cmd("odo", "create", "--s2i", "wildfly", "wo-wait-javaee-git-test", "--project",
commonVar.Project, "--ref", "master", "--git", warGitRepo, "--context", commonVar.Context).ShouldPass()
// Create a URL
helper.Cmd("odo", "url", "create", "gitrepo", "--port", "8080", "--context", commonVar.Context).ShouldPass()
helper.Cmd("odo", "push", "-v", "4", "--context", commonVar.Context).ShouldPass()
routeURL := helper.DetermineRouteURL(commonVar.Context)
// Ping said URL
helper.HttpWaitFor(routeURL, "Insult", 90, 1)
// Delete the component
helper.Cmd("odo", "delete", "-f", "--context", commonVar.Context).ShouldPass()
})
})
// Test Java
Context("odo component creation", func() {
It("Should be able to deploy a .war file using wildfly", func() {
helper.CopyExample(filepath.Join("binary", "java", "wildfly"), commonVar.Context)
helper.Cmd("odo", "create", "--s2i", "wildfly", "javaee-war-test", "--project",
commonVar.Project, "--binary", filepath.Join(commonVar.Context, "ROOT.war"), "--context", commonVar.Context).ShouldPass()
// Create a URL
helper.Cmd("odo", "url", "create", "warfile", "--port", "8080", "--context", commonVar.Context).ShouldPass()
helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass()
routeURL := helper.DetermineRouteURL(commonVar.Context)
// Ping said URL
helper.HttpWaitFor(routeURL, "Sample", 90, 1)
// Delete the component
helper.Cmd("odo", "delete", "-f", "--context", commonVar.Context).ShouldPass()
})
It("Should be able to deploy a git repo that contains a java uberjar application using openjdk", func() {
oc.ImportJavaIS(commonVar.Project)
// Deploy the git repo / wildfly example
helper.Cmd("odo", "create", "--s2i", "java:8", "uberjar-git-test", "--project",
commonVar.Project, "--ref", "master", "--git", jarGitRepo, "--context", commonVar.Context).ShouldPass()
// Create a URL
helper.Cmd("odo", "url", "create", "uberjar", "--port", "8080", "--context", commonVar.Context).ShouldPass()
helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass()
routeURL := helper.DetermineRouteURL(commonVar.Context)
// Ping said URL
helper.HttpWaitFor(routeURL, "Hello World", 90, 1)
// Delete the component
helper.Cmd("odo", "delete", "-f", "--context", commonVar.Context).ShouldPass()
})
It("Should be able to deploy a spring boot uberjar file using openjdk", func() {
oc.ImportJavaIS(commonVar.Project)
helper.CopyExample(filepath.Join("binary", "java", "openjdk"), commonVar.Context)
helper.Cmd("odo", "create", "--s2i", "java:8", "sb-jar-test", "--project",
commonVar.Project, "--binary", filepath.Join(commonVar.Context, "sb.jar"), "--context", commonVar.Context).ShouldPass()
// Create a URL
helper.Cmd("odo", "url", "create", "uberjaropenjdk", "--port", "8080", "--context", commonVar.Context).ShouldPass()
helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass()
routeURL := helper.DetermineRouteURL(commonVar.Context)
// Ping said URL
helper.HttpWaitFor(routeURL, "HTTP Booster", 300, 1)
// Delete the component
helper.Cmd("odo", "delete", "-f", "--context", commonVar.Context).ShouldPass()
})
})
})

View File

@@ -1,159 +0,0 @@
package e2escenarios
import (
"path/filepath"
"runtime"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/openshift/odo/tests/helper"
)
var _ = Describe("odo source e2e tests", func() {
var oc helper.OcRunner
var commonVar helper.CommonVar
// This is run before every Spec (It)
var _ = BeforeEach(func() {
// initialize oc runner
oc = helper.NewOcRunner("oc")
commonVar = helper.CommonBeforeEach()
oc.AddSecret(commonVar)
})
// Clean up after the test
// This is run after every Spec (It)
var _ = AfterEach(func() {
helper.CommonAfterEach(commonVar)
})
Context("odo component creation from source", func() {
JustBeforeEach(func() {
if runtime.GOARCH == "s390x" || runtime.GOARCH == "ppc64le" {
Skip("Skipping test because there is no supported builder image.")
}
})
// issue https://github.com/openshift/odo/issues/4623
// It("Should be able to deploy a wildfly source application", func() {
// helper.CopyExample(filepath.Join("source", "wildfly"), commonVar.Context)
// helper.Cmd("odo", "create", "--s2i", "wildfly", "wildfly-app", "--project",
// commonVar.Project, "--context", commonVar.Context).ShouldPass()
// // Push changes
// helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass()
// cmpList := helper.Cmd("odo", "list", "--context", commonVar.Context).ShouldPass().Out()
// Expect(cmpList).To(ContainSubstring("wildfly-app"))
// // Create a URL
// helper.Cmd("odo", "url", "create", "--port", "8080", "--context", commonVar.Context).ShouldPass()
// helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass()
// routeURL := helper.DetermineRouteURL(commonVar.Context)
// // Ping said URL
// helper.HttpWaitFor(routeURL, "Insult", 30, 1)
// // Delete the component
// helper.Cmd("odo", "app", "delete", "app", "--project", commonVar.Project, "-f").ShouldPass()
// })
// issue https://github.com/openshift/odo/issues/4623
// It("Should be able to deploy a dotnet source application", func() {
// oc.ImportDotnet20IS(commonVar.Project)
// helper.CopyExample(filepath.Join("source", "dotnet"), commonVar.Context)
// helper.Cmd("odo", "create", "--s2i", "dotnet:2.0", "dotnet-app", "--project",
// commonVar.Project, "--context", commonVar.Context).ShouldPass()
// // Push changes
// helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass()
// cmpList := helper.Cmd("odo", "list", "--context", commonVar.Context).ShouldPass().Out()
// Expect(cmpList).To(ContainSubstring("dotnet-app"))
// // Create a URL
// helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass()
// routeURL := helper.DetermineRouteURL(commonVar.Context)
// // Ping said URL
// helper.HttpWaitFor(routeURL, "dotnet", 30, 1)
// // Delete the component
// helper.Cmd("odo", "app", "delete", "app", "--project", commonVar.Project, "-f").ShouldPass()
// })
})
Context("odo component creation", func() {
It("Should be able to deploy an openjdk source application", func() {
oc.ImportJavaIS(commonVar.Project)
helper.CopyExample(filepath.Join("source", "openjdk"), commonVar.Context)
helper.Cmd("odo", "create", "--s2i", "java:8", "openjdk-app", "--project",
commonVar.Project, "--context", commonVar.Context).ShouldPass()
// Push changes
helper.Cmd("odo", "push", "--context", commonVar.Context, "-v", "4").ShouldPass()
cmpList := helper.Cmd("odo", "list", "--context", commonVar.Context).ShouldPass().Out()
Expect(cmpList).To(ContainSubstring("openjdk-app"))
// Create a URL
helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass()
routeURL := helper.DetermineRouteURL(commonVar.Context)
// Ping said URL
helper.HttpWaitFor(routeURL, "Javalin", 30, 1)
// Delete the component
helper.Cmd("odo", "app", "delete", "app", "--project", commonVar.Project, "-f").ShouldPass()
})
It("Should be able to deploy a nodejs source application", func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.Cmd("odo", "create", "--s2i", "nodejs", "nodejs-app", "--project",
commonVar.Project, "--context", commonVar.Context).ShouldPass()
// Push changes
helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass()
cmpList := helper.Cmd("odo", "list", "--context", commonVar.Context).ShouldPass().Out()
Expect(cmpList).To(ContainSubstring("nodejs-app"))
// Create a URL
helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass()
routeURL := helper.DetermineRouteURL(commonVar.Context)
// Ping said URL
helper.HttpWaitFor(routeURL, "node.js", 30, 1)
// Delete the component
helper.Cmd("odo", "app", "delete", "app", "--project", commonVar.Project, "-f").ShouldPass()
})
})
Context("odo component creation, Skip tests for ppc64le arch", func() {
JustBeforeEach(func() {
if runtime.GOARCH == "ppc64le" {
Skip("Skipping test on Power because python is not fully supported by odo, and it is not guaranteed to work.")
}
})
It("Should be able to deploy a python source application", func() {
helper.CopyExample(filepath.Join("source", "python"), commonVar.Context)
helper.Cmd("odo", "create", "--s2i", "python", "python-app", "--project",
commonVar.Project, "--context", commonVar.Context).ShouldPass()
// Push changes
helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass()
cmpList := helper.Cmd("odo", "list", "--context", commonVar.Context).ShouldPass().Out()
Expect(cmpList).To(ContainSubstring("python-app"))
// Create a URL
helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass()
routeURL := helper.DetermineRouteURL(commonVar.Context)
// Ping said URL
helper.HttpWaitFor(routeURL, "WSGI", 30, 1)
// Delete the component
helper.Cmd("odo", "app", "delete", "app", "--project", commonVar.Project, "-f").ShouldPass()
})
})
})

View File

@@ -1,145 +0,0 @@
package integration
import (
"path/filepath"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/openshift/odo/tests/helper"
"github.com/tidwall/gjson"
)
var _ = Describe("odo app command tests", func() {
var commonVar helper.CommonVar
// This is run before every Spec (It)
var _ = BeforeEach(func() {
commonVar = helper.CommonBeforeEach()
})
// Clean up after the test
// This is run after every Spec (It)
var _ = AfterEach(func() {
helper.CommonAfterEach(commonVar)
})
It("should display the help for app command", func() {
appHelp := helper.Cmd("odo", "app", "-h").ShouldPass().Out()
// Trimmed the end of the message string to make it compatible across clusters
Expect(appHelp).To(ContainSubstring("Performs application operations related to"))
})
Context("on a fresh new project", func() {
BeforeEach(func() {
appList := helper.Cmd("odo", "app", "list", "--project", commonVar.Project).ShouldPass().Out()
Expect(appList).To(ContainSubstring("There are no applications deployed"))
actual := helper.Cmd("odo", "app", "list", "-o", "json", "--project", commonVar.Project).ShouldPass().Out()
values := gjson.GetMany(actual, "kind", "metadata", "items")
expected := []string{"List", "{}", "[]"}
Expect(helper.GjsonMatcher(values, expected)).To(Equal(true))
})
It("should fail deleting non existing app", func() {
appDelete := helper.Cmd("odo", "app", "delete", "test", "--project", commonVar.Project, "-f").ShouldFail().Err()
Expect(appDelete).To(ContainSubstring("test app does not exists"))
})
It("should fail describing non existing app", func() {
appDescribe := helper.Cmd("odo", "app", "describe", "test", "--project", commonVar.Project).ShouldFail().Err()
Expect(appDescribe).To(ContainSubstring("test app does not exists"))
})
})
When("creating a new component", func() {
appName := "app"
cmpName := "nodejs"
BeforeEach(func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.Cmd("odo", "component", "create", "--s2i", "nodejs", cmpName, "--app", appName, "--project", commonVar.Project, "--context", commonVar.Context).ShouldPass()
})
When("odo push is executed", func() {
BeforeEach(func() {
helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass()
})
It("should fail describing app without app parameter", func() {
helper.Cmd("odo", "app", "describe", "--project", commonVar.Project).ShouldFail()
})
It("should fail deleting an app without app parameter", func() {
helper.Cmd("odo", "app", "delete", "-f", "--project", commonVar.Project).ShouldFail()
})
It("should list apps", func() {
appListOutput := helper.Cmd("odo", "app", "list", "--project", commonVar.Project).ShouldPass().Out()
Expect(appListOutput).To(ContainSubstring(appName))
})
It("should list apps in JSON format", func() {
actualCompListJSON := helper.Cmd("odo", "app", "list", "-o", "json", "--project", commonVar.Project).ShouldPass().Out()
valuesList := gjson.GetMany(actualCompListJSON, "kind", "items.#.metadata.name", "items.#.metadata.namespace")
expectedList := []string{"List", "app", commonVar.Project}
Expect(helper.GjsonMatcher(valuesList, expectedList)).To(Equal(true))
})
It("should describe specific app", func() {
helper.Cmd("odo", "app", "describe", appName, "--project", commonVar.Project).ShouldPass()
})
It("should describe specific app in JSON format", func() {
actualDesAppJSON := helper.Cmd("odo", "app", "describe", appName, "--project", commonVar.Project, "-o", "json").ShouldPass().Out()
valuesDes := gjson.GetMany(actualDesAppJSON, "kind", "metadata.name", "metadata.namespace")
expectedDes := []string{"Application", appName, commonVar.Project}
Expect(helper.GjsonMatcher(valuesDes, expectedDes)).To(Equal(true))
})
When("changing to context directory", func() {
BeforeEach(func() {
helper.Chdir(commonVar.Context)
})
It("should list apps", func() {
appListOutput := helper.Cmd("odo", "app", "list", "--project", commonVar.Project).ShouldPass().Out()
Expect(appListOutput).To(ContainSubstring(appName))
})
It("should list apps in json format", func() {
actualCompListJSON := helper.Cmd("odo", "list", "-o", "json", "--project", commonVar.Project).ShouldPass().Out()
valuesL := gjson.GetMany(actualCompListJSON, "kind", "devfileComponents.0.metadata.name", "devfileComponents.0.metadata.namespace")
expectedL := []string{"List", "nodejs", commonVar.Project}
Expect(helper.GjsonMatcher(valuesL, expectedL)).To(Equal(true))
})
It("should decsribe app", func() {
helper.Cmd("odo", "app", "describe", "--project", commonVar.Project).ShouldPass()
actualDesAppJSON := helper.Cmd("odo", "app", "describe", "app", "-o", "json", "--project", commonVar.Project).ShouldPass().Out()
valuesDes := gjson.GetMany(actualDesAppJSON, "kind", "metadata.name", "metadata.namespace")
expectedDes := []string{"Application", "app", commonVar.Project}
Expect(helper.GjsonMatcher(valuesDes, expectedDes)).To(Equal(true))
})
})
})
When("adding storage and odo push is executed", func() {
mountPath := "/data"
size := "1Gi"
BeforeEach(func() {
helper.Cmd("odo", "storage", "create", "storage-one", "--context", commonVar.Context, "--path", mountPath, "--size", size).ShouldPass()
helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass()
})
It("should successfully execute describe", func() {
helper.Cmd("odo", "app", "describe", appName, "--project", commonVar.Project).ShouldPass()
})
})
})
})

View File

@@ -1,13 +0,0 @@
// +build !race
package integration
import (
. "github.com/onsi/ginkgo"
)
func componentTestsSub() {
//componentTests("component")
}
var _ = Describe("odo sub component command tests", componentTestsSub)

View File

@@ -1,13 +0,0 @@
// +build !race
package integration
import (
. "github.com/onsi/ginkgo"
)
func componentTestsNoSub() {
componentTests()
}
var _ = Describe("odo component command tests", componentTestsNoSub)

View File

@@ -1,38 +0,0 @@
package integration
import (
. "github.com/onsi/ginkgo"
"github.com/openshift/odo/tests/helper"
//. "github.com/onsi/gomega"
)
var _ = Describe("odo create --s2i command tests", func() {
//var oc helper.OcRunner
var commonVar helper.CommonVar
// This is run before every Spec (It)
var _ = BeforeEach(func() {
// oc = helper.NewOcRunner("oc")
commonVar = helper.CommonBeforeEach()
helper.Chdir(commonVar.Context)
})
// Clean up after the test
// This is run after every Spec (It)
var _ = AfterEach(func() {
helper.CommonAfterEach(commonVar)
})
When("creating a component from s2i wildfly", func() {
BeforeEach(func() {
helper.Cmd("odo", "component", "create", "--s2i", "wildfly", "--project", commonVar.Project).ShouldPass()
// Workaround for https://github.com/openshift/odo/issues/5060
helper.ReplaceString("devfile.yaml", "/usr/local/s2i", "/usr/libexec/s2i")
})
It("should run odo push successfully", func() {
helper.Cmd("odo", "push").ShouldPass()
})
})
})

View File

@@ -1,54 +0,0 @@
package integration
import (
"path/filepath"
"time"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/openshift/odo/tests/helper"
)
var _ = Describe("odo debug command tests", func() {
var commonVar helper.CommonVar
var projName string
// This is run before every Spec (It)
var _ = BeforeEach(func() {
commonVar = helper.CommonBeforeEach()
projName = helper.GetCliRunner().CreateRandNamespaceProjectOfLength(5)
})
// Clean up after the test
// This is run after every Spec (It)
var _ = AfterEach(func() {
helper.CommonAfterEach(commonVar)
helper.GetCliRunner().DeleteNamespaceProject(projName)
})
Context("odo debug on a nodejs:latest component", func() {
It("should expect a ws connection when tried to connect on different debug port locally and remotely", func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.Cmd("odo", "component", "create", "--s2i", "nodejs", "node", "--project", projName, "--context", commonVar.Context).ShouldPass()
helper.Cmd("odo", "env", "set", "--force", "DebugPort", "9292", "--context", commonVar.Context).ShouldPass()
dbgPort := helper.GetLocalEnvInfoValueWithContext("DebugPort", commonVar.Context)
Expect(dbgPort).To(Equal("9292"))
helper.Cmd("odo", "push", "--debug", "--context", commonVar.Context).ShouldPass()
stopChannel := make(chan bool)
go func() {
helper.Cmd("odo", "debug", "port-forward", "--local-port", "5050", "--context", commonVar.Context).WithTerminate(60*time.Second, stopChannel).ShouldRun()
}()
// 400 response expected because the endpoint expects a websocket request and we are doing a HTTP GET
// We are just using this to validate if nodejs agent is listening on the other side
helper.HttpWaitForWithStatus("http://localhost:5050", "WebSockets request was expected", 12, 5, 400)
stopChannel <- true
})
})
})

View File

@@ -124,115 +124,6 @@ var _ = Describe("odo preference and config command tests", func() {
})
})
Context("when setting or unsetting odo local config", func() {
JustBeforeEach(func() {
helper.Chdir(commonVar.Context)
helper.Cmd("odo", "create", "--s2i", "nodejs", "--project", commonVar.Project, "--git", "https://github.com/sclorg/nodejs-ex").ShouldPass()
})
cases := []struct {
paramName string
paramValue string
}{
{
paramName: "Type",
paramValue: "java",
},
{
paramName: "Name",
paramValue: "odo-java",
},
{
paramName: "MinCPU",
paramValue: "0.2",
},
{
paramName: "MaxCPU",
paramValue: "2",
},
{
paramName: "MinMemory",
paramValue: "100M",
},
{
paramName: "MaxMemory",
paramValue: "500M",
},
{
paramName: "Ports",
paramValue: "8080/TCP,45/UDP",
},
{
paramName: "Application",
paramValue: "odotestapp",
},
{
paramName: "Project",
paramValue: "odotestproject",
},
{
paramName: "SourceType",
paramValue: "git",
},
{
paramName: "Ref",
paramValue: "develop",
},
{
paramName: "SourceLocation",
paramValue: "https://github.com/sclorg/nodejs-ex",
},
}
It("should run successfully", func() {
for _, testCase := range cases {
helper.Cmd("odo", "config", "set", testCase.paramName, testCase.paramValue, "-f").ShouldPass()
setValue := helper.GetConfigValue(testCase.paramName)
Expect(setValue).To(ContainSubstring(testCase.paramValue))
// cleanup
helper.Cmd("odo", "config", "unset", testCase.paramName, "-f").ShouldPass()
UnsetValue := helper.GetConfigValue(testCase.paramName)
Expect(UnsetValue).To(BeEmpty())
}
})
It("should run successfully with context", func() {
helper.Chdir(commonVar.OriginalWorkingDirectory)
for _, testCase := range cases {
helper.Cmd("odo", "config", "set", "-f", "--context", commonVar.Context, testCase.paramName, testCase.paramValue).ShouldPass()
configOutput := helper.Cmd("odo", "config", "unset", "-f", "--context", commonVar.Context, testCase.paramName).ShouldPass().Out()
Expect(configOutput).To(ContainSubstring("Local config was successfully updated."))
Value := helper.GetConfigValueWithContext(testCase.paramName, commonVar.Context)
Expect(Value).To(BeEmpty())
}
})
})
Context("when creating odo local config with env variables", func() {
It("should set and unset env variables", func() {
helper.Cmd("odo", "create", "--s2i", "--git", "https://github.com/openshift/nodejs-ex", "nodejs", "--project", commonVar.Project, "--context", commonVar.Context).ShouldPass()
helper.Cmd("odo", "config", "set", "--env", "PORT=4000", "--env", "PORT=1234", "--context", commonVar.Context).ShouldPass()
configPort := helper.GetConfigValueWithContext("PORT", commonVar.Context)
Expect(configPort).To(ContainSubstring("1234"))
helper.Cmd("odo", "config", "set", "--env", "SECRET_KEY=R2lyaXNoIFJhbW5hbmkgaXMgdGhlIGJlc3Q=", "--context", commonVar.Context).ShouldPass()
configSecret := helper.GetConfigValueWithContext("SECRET_KEY", commonVar.Context)
Expect(configSecret).To(ContainSubstring("R2lyaXNoIFJhbW5hbmkgaXMgdGhlIGJlc3Q"))
helper.Cmd("odo", "config", "unset", "--env", "PORT", "--context", commonVar.Context).ShouldPass()
helper.Cmd("odo", "config", "unset", "--env", "SECRET_KEY", "--context", commonVar.Context).ShouldPass()
configValue := helper.Cmd("odo", "config", "view", "--context", commonVar.Context).ShouldPass().Out()
helper.DontMatchAllInOutput(configValue, []string{"PORT", "SECRET_KEY"})
})
It("should check for existence of environment variable in config before unsetting it", func() {
helper.Cmd("odo", "create", "--s2i", "nodejs", "--git", "https://github.com/openshift/nodejs-ex", "--project", commonVar.Project, "--context", commonVar.Context).ShouldPass()
helper.Cmd("odo", "config", "set", "--env", "PORT=4000", "--env", "PORT=1234", "--context", commonVar.Context).ShouldPass()
// unset a valid env var
helper.Cmd("odo", "config", "unset", "--env", "PORT", "--context", commonVar.Context).ShouldPass()
// try to unset an env var that doesn't exist
stdOut := helper.Cmd("odo", "config", "unset", "--env", "nosuchenv", "--context", commonVar.Context).ShouldFail().Err()
Expect(stdOut).To(ContainSubstring("unable to find environment variable nosuchenv in the component"))
})
})
Context("when viewing local config without logging into the OpenShift cluster", func() {
var ocRunner helper.OcRunner
var token string
@@ -267,34 +158,6 @@ var _ = Describe("odo preference and config command tests", func() {
})
})
Context("when using --now with config command", func() {
var oc helper.OcRunner
BeforeEach(func() {
oc = helper.NewOcRunner("oc")
})
It("should successfully set and unset variables", func() {
//set env var
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.Cmd("odo", "create", "--s2i", "nodejs", "nodejs", "--project", commonVar.Project, "--context", commonVar.Context).ShouldPass()
helper.Cmd("odo", "config", "set", "--now", "--env", "hello=world", "--context", commonVar.Context).ShouldPass()
//*Check config
configValue1 := helper.Cmd("odo", "config", "view", "--context", commonVar.Context).ShouldPass().Out()
helper.MatchAllInOutput(configValue1, []string{"hello", "world"})
//*Check dc
envs := oc.GetEnvsDevFileDeployment("nodejs", "app", commonVar.Project)
val, ok := envs["hello"]
Expect(ok).To(BeTrue())
Expect(val).To(ContainSubstring("world"))
// unset a valid env var
helper.Cmd("odo", "config", "unset", "--now", "--env", "hello", "--context", commonVar.Context).ShouldPass()
configValue2 := helper.Cmd("odo", "config", "view", "--context", commonVar.Context).ShouldPass().Out()
helper.DontMatchAllInOutput(configValue2, []string{"hello", "world"})
envs = oc.GetEnvsDevFileDeployment("nodejs", "app", commonVar.Project)
_, ok = envs["hello"]
Expect(ok).To(BeFalse())
})
})
Context("When no ConsentTelemetry preference value is set", func() {
var _ = JustBeforeEach(func() {
// unset the preference in case it is already set

View File

@@ -1,253 +0,0 @@
package integration
import (
"fmt"
"os"
"path/filepath"
"github.com/openshift/odo/pkg/devfile/convert"
"github.com/openshift/odo/tests/helper"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("odo push command tests", func() {
var oc helper.OcRunner
var commonVar helper.CommonVar
appName := "app"
cmpName := "nodejs"
// This is run before every Spec (It)
var _ = BeforeEach(func() {
oc = helper.NewOcRunner("oc")
commonVar = helper.CommonBeforeEach()
})
// Clean up after the test
// This is run after every Spec (It)
var _ = AfterEach(func() {
helper.CommonAfterEach(commonVar)
})
// Timeout not respected by devfile https://github.com/openshift/odo/issues/4529
// Context("Check pod timeout", func() {
// It("Check that pod timeout works and we time out immediately..", func() {
// helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
// helper.CmdShouldPass("odo", "component", "create", "--s2i", "nodejs", cmpName, "--project", commonVar.Project, "--context", commonVar.Context, "--app", appName)
// helper.CmdShouldPass("odo", "preference", "set", "PushTimeout", "1")
// output := helper.CmdShouldFail("odo", "push", "--context", commonVar.Context)
// Expect(output).To(ContainSubstring("waited 1s but couldn't find running pod matching selector"))
// })
// })
Context("Test push outside of the current working direcory", func() {
// Change to "outside" the directory before running the below tests
JustBeforeEach(func() {
helper.Chdir(commonVar.Context)
})
It("Push, modify a file and then push outside of the working directory", func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.Cmd("odo", "component", "create", "--s2i", "nodejs", cmpName, "--project", commonVar.Project, "--context", commonVar.Context, "--app", appName).ShouldPass()
helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass()
// Create a new file to test propagating changes
newFilePath := filepath.Join(commonVar.Context, "foobar.txt")
if err := helper.CreateFileWithContent(newFilePath, "hello world"); err != nil {
fmt.Printf("the foobar.txt file was not created, reason %v", err.Error())
}
// Test propagating changes
helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass()
// Delete the file and check that the file is deleted
helper.DeleteDir(newFilePath)
// Test propagating deletions
helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass()
})
})
Context("when push command is executed", func() {
It("should be able to create a file, push, delete, then push again propagating the deletions and build", func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.Cmd("odo", "component", "create", "--s2i", "nodejs", cmpName, "--project", commonVar.Project, "--context", commonVar.Context, "--app", appName).ShouldPass()
helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass()
output := helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass().Out()
Expect(output).To(ContainSubstring("No file changes detected, skipping build"))
// Create a new file that we plan on deleting later...
newFilePath := filepath.Join(commonVar.Context, "foobar.txt")
if err := helper.CreateFileWithContent(newFilePath, "hello world"); err != nil {
fmt.Printf("the foobar.txt file was not created, reason %v", err.Error())
}
// Create a new directory
newDirPath := filepath.Join(commonVar.Context, "testdir")
helper.MakeDir(newDirPath)
// Push
helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass()
// Check to see if it's been pushed (foobar.txt abd directory testdir)
podName := oc.GetRunningPodNameByComponent(cmpName, commonVar.Project)
stdOut := oc.ExecListDir(podName, commonVar.Project, convert.DefaultSourceMappingS2i)
helper.MatchAllInOutput(stdOut, []string{"foobar.txt", "testdir"})
// Now we delete the file and dir and push
helper.DeleteDir(newFilePath)
helper.DeleteDir(newDirPath)
helper.Cmd("odo", "push", "--context", commonVar.Context, "-v4").ShouldPass()
// Then check to see if it's truly been deleted
stdOut = oc.ExecListDir(podName, commonVar.Project, convert.DefaultSourceMappingS2i)
helper.DontMatchAllInOutput(stdOut, []string{"foobar.txt", "testdir"})
})
It("should build when a file and a folder is renamed in the directory", func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.Cmd("odo", "component", "create", "--s2i", "nodejs", cmpName, "--project", commonVar.Project, "--context", commonVar.Context, "--app", appName).ShouldPass()
// create a file and folder then push
err := os.MkdirAll(filepath.Join(commonVar.Context, "tests"), 0750)
Expect(err).To(BeNil())
testFile, err := os.Create(filepath.Join(commonVar.Context, "README.md"))
testFile.Close()
Expect(err).To(BeNil())
helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass()
output := helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass().Out()
Expect(output).To(ContainSubstring("No file changes detected, skipping build"))
// rename a file and push
helper.RenameFile(filepath.Join(commonVar.Context, "README.md"), filepath.Join(commonVar.Context, "NEW-FILE.md"))
output = helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass().Out()
Expect(output).To(Not(ContainSubstring("No file changes detected, skipping build")))
// get the name of running pod
podName := oc.GetRunningPodNameByComponent(cmpName, commonVar.Project)
// verify that the new file was pushed
stdOut := oc.ExecListDir(podName, commonVar.Project, convert.DefaultSourceMappingS2i)
Expect(stdOut).To(Not(ContainSubstring("README.md")))
Expect(stdOut).To(ContainSubstring("NEW-FILE.md"))
// rename a folder and push
helper.RenameFile(filepath.Join(commonVar.Context, "tests"), filepath.Join(commonVar.Context, "testing"))
output = helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass().Out()
Expect(output).To(Not(ContainSubstring("No file changes detected, skipping build")))
// verify that the new file was pushed
stdOut = oc.ExecListDir(podName, commonVar.Project, convert.DefaultSourceMappingS2i)
Expect(stdOut).To(Not(ContainSubstring("tests")))
Expect(stdOut).To(ContainSubstring("testing"))
})
It("should push only the modified files", func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.Cmd("odo", "component", "create", "--s2i", "nodejs:latest", cmpName, "--project", commonVar.Project, "--context", commonVar.Context, "--app", appName).ShouldPass()
helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass()
url := oc.GetFirstURL(cmpName, appName, commonVar.Project)
// Wait for running app before getting info about files.
// During the startup sequence there is something that will modify the access time of a source file.
helper.HttpWaitFor("http://"+url, "Hello world from node.js!", 30, 1)
earlierCatServerFile := ""
earlierCatServerFile = helper.StatFileInPodContainer(oc, cmpName, convert.ContainerName, appName, commonVar.Project, filepath.ToSlash(filepath.Join(convert.DefaultSourceMappingS2i, "server.js")))
earlierCatPackageFile := ""
earlierCatPackageFile = helper.StatFileInPodContainer(oc, cmpName, convert.ContainerName, appName, commonVar.Project, filepath.ToSlash(filepath.Join(convert.DefaultSourceMappingS2i, "package.json")))
helper.ReplaceString(filepath.Join(commonVar.Context, "server.js"), "Hello world from node.js!", "UPDATED!")
helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass()
helper.HttpWaitFor("http://"+url, "UPDATED!", 30, 1)
modifiedCatPackageFile := ""
modifiedCatPackageFile = helper.StatFileInPodContainer(oc, cmpName, convert.ContainerName, appName, commonVar.Project, filepath.ToSlash(filepath.Join(convert.DefaultSourceMappingS2i, "package.json")))
modifiedCatServerFile := ""
modifiedCatServerFile = helper.StatFileInPodContainer(oc, cmpName, convert.ContainerName, appName, commonVar.Project, filepath.ToSlash(filepath.Join(convert.DefaultSourceMappingS2i, "server.js")))
Expect(modifiedCatPackageFile).To(Equal(earlierCatPackageFile))
Expect(modifiedCatServerFile).NotTo(Equal(earlierCatServerFile))
})
})
Context("when .odoignore file exists", func() {
// works
It("should create and push the contents of a named component excluding the contents and changes detected in .odoignore file", func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
ignoreFilePath := filepath.Join(commonVar.Context, ".odoignore")
if err := helper.CreateFileWithContent(ignoreFilePath, ".git\n*.md"); err != nil {
fmt.Printf("the .odoignore file was not created, reason %v", err.Error())
}
_, err := os.Create(filepath.Join(commonVar.Context, "README.md"))
Expect(err).To(BeNil())
helper.Cmd("odo", "create", "--s2i", "nodejs", "nodejs", "--project", commonVar.Project, "--context", commonVar.Context).ShouldPass()
helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass()
// get the name of running pod
podName := oc.GetRunningPodNameByComponent("nodejs", commonVar.Project)
// verify that the server file got pushed
stdOut1 := oc.ExecListDir(podName, commonVar.Project, convert.DefaultSourceMappingS2i)
Expect(stdOut1).To(ContainSubstring("server.js"))
// verify that the README.md file was not pushed
stdOut3 := oc.ExecListDir(podName, commonVar.Project, convert.DefaultSourceMappingS2i)
Expect(stdOut3).To(Not(ContainSubstring(("README.md"))))
// modify a ignored file and push
helper.ReplaceString(filepath.Join(commonVar.Context, "README.md"), "", "This is a example welcome page!")
output := helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass().Out()
Expect(output).To(ContainSubstring("No file changes detected, skipping build"))
// test ignores using the flag
output = helper.Cmd("odo", "push", "--context", commonVar.Context, "--ignore", "*.md").ShouldPass().Out()
Expect(output).To(ContainSubstring("No file changes detected, skipping build"))
})
})
Context("when .gitignore file exists or not", func() {
It("should create and push the contents of a named component and include odo-file-index.json path to .gitignore file to exclude the contents, if does not exists create one", func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.Cmd("odo", "component", "create", "--s2i", "nodejs", cmpName, "--project", commonVar.Project, "--context", commonVar.Context, "--app", appName).ShouldPass()
// push and include the odo-file-index.json path to .gitignore file
helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass()
ignoreFilePath := filepath.Join(commonVar.Context, ".gitignore")
helper.FileShouldContainSubstring(ignoreFilePath, filepath.Join(".odo", "odo-file-index.json"))
})
})
Context("when running odo push with flag --show-log", func() {
It("should be able to execute odo push consecutively without breaking anything", func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.Cmd("odo", "create", "--s2i", "nodejs", "nodejs", "--project", commonVar.Project, "--context", commonVar.Context).ShouldPass()
// Run odo push in consecutive iteration
output := helper.Cmd("odo", "push", "--show-log", "--context", commonVar.Context).ShouldPass().Out()
Expect(output).To(Not(ContainSubstring("No file changes detected, skipping build")))
for i := 0; i <= 1; i++ {
output := helper.Cmd("odo", "push", "--show-log", "--context", commonVar.Context).ShouldPass().Out()
Expect(output).To(ContainSubstring("No file changes detected, skipping build"))
}
})
})
})

View File

@@ -1,115 +0,0 @@
package integration
import (
"path/filepath"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/openshift/odo/tests/helper"
"github.com/tidwall/gjson"
)
var _ = Describe("odo storage command tests", func() {
var commonVar helper.CommonVar
// This is run before every Spec (It)
var _ = BeforeEach(func() {
commonVar = helper.CommonBeforeEach()
})
// Clean up after the test
// This is run after every Spec (It)
var _ = AfterEach(func() {
helper.CommonAfterEach(commonVar)
})
It("should display the help for storage command", func() {
appHelp := helper.Cmd("odo", "storage", "-h").ShouldPass().Out()
Expect(appHelp).To(ContainSubstring("Perform storage operations"))
})
When("creating a new component", func() {
BeforeEach(func() {
helper.CopyExample(filepath.Join("source", "wildfly"), commonVar.Context)
helper.Cmd("odo", "component", "create", "--s2i", "wildfly", "wildfly", "--app", "wildflyapp", "--project", commonVar.Project, "--context", commonVar.Context).ShouldPass()
})
When("creating storage", func() {
actualJSONStorage := ""
BeforeEach(func() {
// create storage
actualJSONStorage = helper.Cmd("odo", "storage", "create", "mystorage", "--path=/opt/app-root/src/storage/", "--size=1Gi", "--context", commonVar.Context, "-o", "json").ShouldPass().Out()
})
AfterEach(func() {
helper.Cmd("odo", "storage", "delete", "mystorage", "--context", commonVar.Context, "-f").ShouldPass()
})
It("should create", func() {
valuesStoreC := gjson.GetMany(actualJSONStorage, "kind", "metadata.name", "spec.size", "spec.path")
expectedStoreC := []string{"Storage", "mystorage", "1Gi", "/opt/app-root/src/storage/"}
Expect(helper.GjsonMatcher(valuesStoreC, expectedStoreC)).To(Equal(true))
})
When("listing storage in json", func() {
actualStorageList := ""
BeforeEach(func() {
actualStorageList = helper.Cmd("odo", "storage", "list", "--context", commonVar.Context, "-o", "json").ShouldPass().Out()
})
It("should list output in json format", func() {
valuesStoreL := gjson.GetMany(actualStorageList, "kind", "items.2.kind", "items.2.metadata.name", "items.2.spec.size")
expectedStoreL := []string{"List", "Storage", "mystorage", "1Gi"}
Expect(helper.GjsonMatcher(valuesStoreL, expectedStoreL)).To(Equal(true))
})
})
})
})
When("component is created and pushed", func() {
BeforeEach(func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.Cmd("odo", "component", "create", "--s2i", "nodejs", "nodejs", "--app", "nodeapp", "--project", commonVar.Project, "--context", commonVar.Context).ShouldPass()
helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass()
})
When("creating storage", func() {
BeforeEach(func() {
helper.Cmd("odo", "storage", "create", "pv1", "--path=/tmp1", "--size=1Gi", "--context", commonVar.Context).ShouldPass()
})
It("should list storage as Not Pushed", func() {
StorageList := helper.Cmd("odo", "storage", "list", "--context", commonVar.Context).ShouldPass().Out()
Expect(StorageList).To(ContainSubstring("Not Pushed"))
})
When("storage is pushed", func() {
BeforeEach(func() {
helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass()
})
It("should have state push", func() {
StorageList := helper.Cmd("odo", "storage", "list", "--context", commonVar.Context).ShouldPass().Out()
Expect(StorageList).To(ContainSubstring("Pushed"))
})
When("storage is deleted", func() {
BeforeEach(func() {
helper.Cmd("odo", "storage", "delete", "pv1", "-f", "--context", commonVar.Context).ShouldPass()
})
It("should have state Locally Deleted", func() {
StorageList := helper.Cmd("odo", "storage", "list", "--context", commonVar.Context).ShouldPass().Out()
Expect(StorageList).To(ContainSubstring("Locally Deleted"))
})
})
})
})
})
})

View File

@@ -1,137 +0,0 @@
package integration
import (
"path/filepath"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/openshift/odo/tests/helper"
"github.com/tidwall/gjson"
)
var _ = Describe("odo url command tests", func() {
var commonVar helper.CommonVar
// This is run before every Spec (It)
var _ = BeforeEach(func() {
commonVar = helper.CommonBeforeEach()
})
// Clean up after the test
// This is run after every Spec (It)
var _ = AfterEach(func() {
helper.CommonAfterEach(commonVar)
})
Context("Listing urls", func() {
It("should list appropriate URLs and push message", func() {
var stdout string
url1 := helper.RandString(5)
url2 := helper.RandString(5)
componentName := helper.RandString(6)
helper.Cmd("odo", "create", "--s2i", "nodejs", "--context", commonVar.Context, "--project", commonVar.Project, componentName, "--ref", "master", "--git", "https://github.com/openshift/nodejs-ex", "--port", "8080,8000").ShouldPass()
helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass()
stdout = helper.Cmd("odo", "url", "list", "--context", commonVar.Context).ShouldFail().Err()
Expect(stdout).To(ContainSubstring("no URLs found"))
helper.Cmd("odo", "url", "create", url1, "--port", "8080", "--context", commonVar.Context).ShouldPass()
stdout = helper.Cmd("odo", "url", "list", "--context", commonVar.Context).ShouldPass().Out()
helper.MatchAllInOutput(stdout, []string{url1, "Not Pushed", url1, "odo push", "<provided by cluster>"})
helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass()
stdout = helper.Cmd("odo", "url", "list", "--context", commonVar.Context).ShouldPass().Out()
helper.MatchAllInOutput(stdout, []string{url1, "Pushed"})
helper.DontMatchAllInOutput(stdout, []string{"Not Pushed", "odo push"})
helper.Cmd("odo", "url", "delete", url1, "-f", "--context", commonVar.Context).ShouldPass()
stdout = helper.Cmd("odo", "url", "list", "--context", commonVar.Context).ShouldPass().Out()
helper.MatchAllInOutput(stdout, []string{url1, "Locally Deleted", url1, "odo push"})
helper.Cmd("odo", "url", "create", url2, "--port", "8000", "--context", commonVar.Context).ShouldPass()
stdout = helper.Cmd("odo", "url", "list", "--context", commonVar.Context).ShouldPass().Out()
helper.MatchAllInOutput(stdout, []string{url1, "Locally Deleted", url2, "Not Pushed", "odo push"})
helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass()
stdout = helper.Cmd("odo", "url", "list", "--context", commonVar.Context).ShouldPass().Out()
helper.MatchAllInOutput(stdout, []string{url2, "Pushed"})
helper.DontMatchAllInOutput(stdout, []string{url1, "Not Pushed", "odo push"})
})
It("should create a secure URL", func() {
url1 := helper.RandString(5)
componentName := helper.RandString(6)
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.Cmd("odo", "create", "--s2i", "nodejs", "--context", commonVar.Context, "--project", commonVar.Project, componentName).ShouldPass()
helper.Cmd("odo", "url", "create", url1, "--port", "8080", "--context", commonVar.Context, "--secure").ShouldPass()
stdout := helper.Cmd("odo", "url", "list", "--context", commonVar.Context).ShouldPass().Out()
helper.MatchAllInOutput(stdout, []string{url1, "Not Pushed", "true"})
helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass()
secureURLs := helper.DetermineRouteURLs(commonVar.Context)
Expect(secureURLs).To(ContainElement(ContainSubstring("https")))
helper.HttpWaitFor(secureURLs[0], "Hello world from node.js!", 20, 1)
stdout = helper.Cmd("odo", "url", "list", "--context", commonVar.Context).ShouldPass().Out()
helper.MatchAllInOutput(stdout, []string{secureURLs[0], "Pushed", "true"})
helper.Cmd("odo", "delete", "-f", "--context", commonVar.Context).ShouldPass()
})
})
Context("when listing urls using -o json flag", func() {
JustBeforeEach(func() {
helper.Chdir(commonVar.Context)
})
It("should be able to list url in machine readable json format", func() {
helper.Cmd("odo", "create", "--s2i", "nodejs", "nodejs", "--app", "myapp", "--project", commonVar.Project, "--git", "https://github.com/openshift/nodejs-ex").ShouldPass()
helper.Cmd("odo", "url", "create", "myurl").ShouldPass()
helper.Cmd("odo", "push").ShouldPass()
// odo url list -o json
actualURLListJSON := helper.Cmd("odo", "url", "list", "-o", "json").ShouldPass().Out()
valuesURLL := gjson.GetMany(actualURLListJSON, "kind", "items.0.kind", "items.0.metadata.name", "items.0.spec.kind", "items.0.status.state")
expectedURLL := []string{"List", "URL", "myurl", "route", "Pushed"}
Expect(helper.GjsonMatcher(valuesURLL, expectedURLL)).To(Equal(true))
})
It("should be able to list url in machine readable json format for a secure url", func() {
helper.Cmd("odo", "create", "--s2i", "nodejs", "nodejs", "--app", "myapp", "--project", commonVar.Project, "--git", "https://github.com/openshift/nodejs-ex").ShouldPass()
helper.Cmd("odo", "url", "create", "myurl", "--secure").ShouldPass()
actualURLListJSON := helper.Cmd("odo", "url", "list", "-o", "json").ShouldPass().Out()
valuesURLLJ := gjson.GetMany(actualURLListJSON, "kind", "items.0.kind", "items.0.metadata.name", "items.0.spec.port", "items.0.status.state")
expectedURLLJ := []string{"List", "URL", "myurl", "8080", "Not Pushed"}
Expect(helper.GjsonMatcher(valuesURLLJ, expectedURLLJ)).To(Equal(true))
helper.Cmd("odo", "push").ShouldPass()
// odo url list -o json
actualURLListJSON = helper.Cmd("odo", "url", "list", "-o", "json").ShouldPass().Out()
valuesURLLJP := gjson.GetMany(actualURLListJSON, "kind", "items.0.kind", "items.0.metadata.name", "items.0.spec.port", "items.0.spec.secure", "items.0.status.state")
expectedURLLJP := []string{"List", "URL", "myurl", "8080", "true", "Pushed"}
Expect(helper.GjsonMatcher(valuesURLLJP, expectedURLLJP)).To(Equal(true))
})
})
Context("when using --now flag with url create / delete", func() {
It("should create and delete url on cluster successfully with now flag", func() {
url1 := helper.RandString(5)
componentName := helper.RandString(6)
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.Cmd("odo", "create", "--s2i", "nodejs", "--context", commonVar.Context, "--project", commonVar.Project, componentName, "--ref", "master", "--git", "https://github.com/openshift/nodejs-ex", "--port", "8080,8000").ShouldPass()
helper.Cmd("odo", "url", "create", url1, "--context", commonVar.Context, "--port", "8080", "--now").ShouldPass()
out1 := helper.Cmd("odo", "url", "list", "--context", commonVar.Context).ShouldPass().Out()
helper.MatchAllInOutput(out1, []string{url1, "Pushed", url1})
helper.DontMatchAllInOutput(out1, []string{"odo push"})
routeURL := helper.DetermineRouteURL(commonVar.Context)
// Ping said URL
helper.HttpWaitFor(routeURL, "Node.js", 30, 1)
helper.Cmd("odo", "url", "delete", url1, "--context", commonVar.Context, "--now", "-f").ShouldPass()
out2 := helper.Cmd("odo", "url", "list", "--context", commonVar.Context).ShouldFail().Err()
Expect(out2).To(ContainSubstring("no URLs found"))
})
})
})

View File

@@ -1,61 +0,0 @@
package integration
import (
"path/filepath"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/openshift/odo/tests/helper"
)
var _ = Describe("odo watch command tests", func() {
var commonVar helper.CommonVar
// This is run before every Spec (It)
var _ = BeforeEach(func() {
commonVar = helper.CommonBeforeEach()
})
// Clean up after the test
// This is run after every Spec (It)
var _ = AfterEach(func() {
helper.CommonAfterEach(commonVar)
})
Context("when running help for watch command", func() {
It("should display the help", func() {
appHelp := helper.Cmd("odo", "watch", "-h").ShouldPass().Out()
helper.MatchAllInOutput(appHelp, []string{"Watch for changes", "git components"})
})
})
Context("when executing watch without pushing the component", func() {
It("should fail", func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.Cmd("odo", "component", "create", "--s2i", "nodejs", "--project", commonVar.Project, "--context", commonVar.Context).ShouldPass()
output := helper.Cmd("odo", "watch", "--context", commonVar.Context).ShouldFail().Err()
Expect(output).To(ContainSubstring("component does not exist. Please use `odo push` to create your component"))
})
})
Context("when executing odo watch against an app that doesn't exist", func() {
JustBeforeEach(func() {
helper.Chdir(commonVar.Context)
})
It("should fail with proper error", func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.Cmd("odo", "component", "create", "--s2i", "nodejs", "--project", commonVar.Project).ShouldPass()
output := helper.Cmd("odo", "watch", "--app", "dummy").ShouldFail().Err()
Expect(output).To(ContainSubstring("component does not exist"))
})
})
Context("when executing watch on a git source type component", func() {
It("should fail", func() {
helper.Cmd("odo", "create", "--s2i", "--context", commonVar.Context, "nodejs", "--git", "https://github.com/openshift/nodejs-ex.git").ShouldPass()
output := helper.Cmd("odo", "watch", "--context", commonVar.Context).ShouldFail().Err()
Expect(output).To(ContainSubstring("Watch is supported by binary and local components only"))
})
})
})

View File

@@ -1,779 +0,0 @@
package integration
import (
"fmt"
"io/ioutil"
"os"
"path"
"path/filepath"
"runtime"
"time"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/openshift/odo/tests/helper"
"github.com/tidwall/gjson"
)
func componentTests(args ...string) {
var oc helper.OcRunner
var commonVar helper.CommonVar
var appName string
var cmpName string
cmpNameDefault := "nodejs"
// This is run before every Spec (It)
var _ = BeforeEach(func() {
oc = helper.NewOcRunner("oc")
commonVar = helper.CommonBeforeEach()
appName = "app-" + helper.RandString(5)
cmpName = "cmp-" + helper.RandString(5)
})
// Clean up after the test
// This is run after every Spec (It)
var _ = AfterEach(func() {
helper.CommonAfterEach(commonVar)
})
It("should fail if json is non-existent for a command", func() {
output := helper.Cmd("odo", "version", "-o", "json").ShouldFail().Err()
Expect(output).To(ContainSubstring("Machine readable output is not yet implemented for this command"))
})
It("should not have machine output for odo version", func() {
output := helper.Cmd("odo", "version", "--help").ShouldPass().Out()
Expect(output).NotTo(ContainSubstring("Specify output format, supported format: json"))
})
XIt("should be able to create a git component and update it from local to git", func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.Cmd("odo", append(args, "create", "--s2i", "nodejs", cmpName, "--project", commonVar.Project, "--context", commonVar.Context, "--app", appName)...).ShouldPass()
helper.Cmd("odo", append(args, "push", "--context", commonVar.Context)...).ShouldPass()
helper.Cmd("odo", "update", "--git", "https://github.com/openshift/nodejs-ex.git", "--context", commonVar.Context).ShouldPass()
// check the source location and type in the deployment config
getSourceLocation := oc.SourceLocationDC(cmpName, appName, commonVar.Project)
Expect(getSourceLocation).To(ContainSubstring("https://github.com/openshift/nodejs-ex"))
getSourceType := oc.SourceTypeDC(cmpName, appName, commonVar.Project)
Expect(getSourceType).To(ContainSubstring("git"))
})
XIt("should be able to update a component from git to local", func() {
helper.Cmd("odo", append(args, "create", "--s2i", "nodejs", cmpName, "--project", commonVar.Project, "--git", "https://github.com/openshift/nodejs-ex", "--context", commonVar.Context, "--app", appName)...).ShouldPass()
helper.Cmd("odo", append(args, "push", "--context", commonVar.Context)...).ShouldPass()
// update the component config according to the git component
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.Cmd("odo", "update", "--local", "./", "--context", commonVar.Context).ShouldPass()
// check the source location and type in the deployment config
getSourceLocation := oc.SourceLocationDC(cmpName, appName, commonVar.Project)
Expect(getSourceLocation).To(ContainSubstring(""))
getSourceType := oc.SourceTypeDC(cmpName, appName, commonVar.Project)
Expect(getSourceType).To(ContainSubstring("local"))
})
XIt("should pass outside a odo directory with component name as parameter", func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.Cmd("odo", append(args, "create", "--s2i", "nodejs", cmpNameDefault, "--app", appName, "--project", commonVar.Project, "--context", commonVar.Context)...).ShouldPass()
info := helper.LocalEnvInfo(commonVar.Context)
Expect(info.GetApplication(), appName)
Expect(info.GetName(), cmpNameDefault)
helper.Cmd("odo", append(args, "push", "--context", commonVar.Context)...).ShouldPass()
cmpListOutput := helper.Cmd("odo", append(args, "list", "--app", appName, "--project", commonVar.Project)...).ShouldPass()
Expect(cmpListOutput).To(ContainSubstring(cmpNameDefault))
actualDesCompJSON := helper.Cmd("odo", append(args, "describe", cmpNameDefault, "--app", appName, "--project", commonVar.Project, "-o", "json")...).ShouldPass().Out()
valuesDescCJ := gjson.GetMany(actualDesCompJSON, "kind", "metadata.name", "spec.app", "spec.type", "status.state")
expectedDescCJ := []string{"Component", "nodejs", "app", "nodejs", "Pushed"}
Expect(helper.GjsonMatcher(valuesDescCJ, expectedDescCJ)).To(Equal(true))
helper.Cmd("odo", append(args, "delete", cmpNameDefault, "--app", appName, "--project", commonVar.Project, "-f")...).ShouldPass()
})
It("should retain the same environment variable on multiple push", func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.Cmd("odo", append(args, "create", "--s2i", "nodejs", cmpName, "--app", appName, "--project", commonVar.Project, "--context", commonVar.Context)...).ShouldPass()
helper.Cmd("odo", append(args, "push", "--context", commonVar.Context)...).ShouldPass()
helper.Chdir(commonVar.Context)
helper.Cmd("odo", "config", "set", "--env", "FOO=BAR").ShouldPass()
helper.Cmd("odo", append(args, "push")...).ShouldPass()
info := helper.LocalEnvInfo(commonVar.Context)
Expect(info.GetApplication(), appName)
Expect(info.GetName(), cmpName)
envVars := oc.GetEnvsDevFileDeployment(cmpName, appName, commonVar.Project)
val, ok := envVars["FOO"]
Expect(ok).To(BeTrue())
Expect(val).To(Equal("BAR"))
})
It("should print deprecation warning when creating a S2I component", func() {
// Note: Remove these tests once the S2I cleanup is done, see https://github.com/openshift/odo/issues/4932.
// We are using .Err() since warnings are considered as a part of Error
stdOut := helper.Cmd("odo", "create", "nodejs", "--s2i", "--context", commonVar.Context).ShouldPass().Err()
Expect(stdOut).To(ContainSubstring("S2I components Deprecated"))
})
It("should print deprecation warning when creating and pushing a S2I git component", func() {
// Note: Remove these tests once the S2I cleanup is done, see https://github.com/openshift/odo/issues/4932.
// We are using .Err() since warnings are considered as a part of Error
stdOut := helper.Cmd("odo", "create", "nodejs", "--s2i", "--git", "https://github.com/openshift/nodejs-ex.git", "--context", commonVar.Context).ShouldPass().Err()
Expect(stdOut).To(ContainSubstring("S2I components Deprecated"))
stdOut = helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldRun().Err()
Expect(stdOut).To(ContainSubstring("S2I components Deprecated"))
})
It("should print deprecation warning when creating and pushing a S2I binary component", func() {
// Note: Remove these tests once the S2I cleanup is done, see https://github.com/openshift/odo/issues/4932.
helper.CopyExample(filepath.Join("binary", "java", "openjdk"), commonVar.Context)
// We are using .Err() since warnings are considered as a part of Error
stdOut := helper.Cmd("odo", "create", "java:8", "sb-jar-test", "--s2i", "--binary", filepath.Join(commonVar.Context, "sb.jar"), "--context", commonVar.Context).ShouldPass().Err()
Expect(stdOut).To(ContainSubstring("S2I components Deprecated"))
stdOut = helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldRun().Err()
Expect(stdOut).To(ContainSubstring("S2I components Deprecated"))
})
When("in context directory", func() {
BeforeEach(func() {
helper.Chdir(commonVar.Context)
})
It("should show an error when ref flag is provided with sources except git", func() {
outputErr := helper.Cmd("odo", append(args, "create", "--s2i", "nodejs", "--project", commonVar.Project, cmpName, "--ref", "test")...).ShouldFail().Err()
Expect(outputErr).To(ContainSubstring("the --ref flag is only valid for --git flag"))
})
It("should succeed listing catalog components", func() {
// Since components catalog is constantly changing, we simply check to see if this command passes.. rather than checking the JSON each time.
helper.Cmd("odo", "catalog", "list", "components", "-o", "json").ShouldPass()
})
It("should fail the create command as --git flag, which is specific to s2i component creation, is used without --s2i flag", func() {
output := helper.Cmd("odo", "create", "nodejs", cmpName, "--git", "https://github.com/openshift/nodejs-ex", "--context", commonVar.Context, "--app", appName).ShouldFail().Err()
Expect(output).Should(ContainSubstring("flag --git, requires --s2i flag to be set, when deploying S2I (Source-to-Image) components"))
})
It("should fail the create command as --binary flag, which is specific to s2i component creation, is used without --s2i flag", func() {
helper.CopyExample(filepath.Join("binary", "java", "openjdk"), commonVar.Context)
output := helper.Cmd("odo", "create", "java:8", "sb-jar-test", "--binary", filepath.Join(commonVar.Context, "sb.jar"), "--context", commonVar.Context).ShouldFail().Err()
Expect(output).Should(ContainSubstring("flag --binary, requires --s2i flag to be set, when deploying S2I (Source-to-Image) components"))
})
It("should work for s2i component from a devfile directory", func() {
newContext := path.Join(commonVar.Context, "newContext")
helper.MakeDir(newContext)
helper.Chdir(newContext)
cmpName2 := helper.RandString(6)
helper.Cmd("odo", "create", "--starter", "nodejs").ShouldPass()
context2 := helper.CreateNewContext()
helper.Cmd("odo", "create", "--s2i", "nodejs", "--context", context2, cmpName2).ShouldPass()
output := helper.Cmd("odo", "describe", "--context", context2).ShouldPass().Out()
Expect(output).To(ContainSubstring(fmt.Sprint("Component Name: ", cmpName2)))
helper.Chdir(commonVar.OriginalWorkingDirectory)
helper.DeleteDir(context2)
})
It("should list the component in the same app when one is pushed and the other one is not pushed", func() {
helper.Chdir(commonVar.OriginalWorkingDirectory)
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.Cmd("odo", append(args, "create", "--s2i", "nodejs", cmpName, "--project", commonVar.Project, "--context", commonVar.Context, "--app", appName)...).ShouldPass()
info := helper.LocalEnvInfo(commonVar.Context)
Expect(info.GetApplication(), appName)
Expect(info.GetName(), cmpName)
helper.Cmd("odo", append(args, "push", "--context", commonVar.Context)...).ShouldPass()
context2 := helper.CreateNewContext()
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.Cmd("odo", append(args, "create", "--s2i", "nodejs", "cmp-git-2", "--project", commonVar.Project, "--context", context2, "--app", appName)...).ShouldPass()
info = helper.LocalEnvInfo(context2)
Expect(info.GetApplication(), appName)
Expect(info.GetName(), "cmp-git-2")
cmpList := helper.Cmd("odo", append(args, "list", "--context", context2)...).ShouldPass().Out()
helper.MatchAllInOutput(cmpList, []string{cmpName, "cmp-git-2", "Not Pushed", "Pushed"})
helper.Cmd("odo", append(args, "delete", "-f", "--all", "--context", commonVar.Context)...).ShouldPass()
helper.Cmd("odo", append(args, "delete", "-f", "--all", "--context", context2)...).ShouldPass()
helper.DeleteDir(context2)
})
It("should create a local python component, push it and then delete it using --all flag", func() {
helper.CopyExample(filepath.Join("source", "python"), commonVar.Context)
helper.Cmd("odo", append(args, "create", "--s2i", "python", cmpName, "--app", appName, "--project", commonVar.Project, "--context", commonVar.Context)...).ShouldPass()
info := helper.LocalEnvInfo(commonVar.Context)
Expect(info.GetApplication(), appName)
Expect(info.GetName(), cmpName)
helper.Cmd("odo", append(args, "push", "--context", commonVar.Context)...).ShouldPass()
helper.Cmd("odo", append(args, "delete", "--context", commonVar.Context, "-f")...).ShouldPass()
helper.Cmd("odo", append(args, "delete", "--all", "-f", "--context", commonVar.Context)...).ShouldPass()
componentList := helper.Cmd("odo", append(args, "list", "--app", appName, "--project", commonVar.Project)...).ShouldPass().Out()
Expect(componentList).NotTo(ContainSubstring(cmpName))
files := helper.ListFilesInDir(commonVar.Context)
Expect(files).NotTo(ContainElement(".odo"))
})
It("should create a local python component, push it and then delete it using --all flag in local directory", func() {
helper.CopyExample(filepath.Join("source", "python"), commonVar.Context)
helper.Cmd("odo", append(args, "create", "--s2i", "python", cmpName, "--app", appName, "--project", commonVar.Project)...).ShouldPass()
info := helper.LocalEnvInfo(commonVar.Context)
Expect(info.GetApplication(), appName)
Expect(info.GetName(), cmpName)
helper.Cmd("odo", append(args, "push")...).ShouldPass()
helper.Cmd("odo", append(args, "delete", "--all", "-f")...).ShouldPass()
componentList := helper.Cmd("odo", append(args, "list", "--app", appName, "--project", commonVar.Project)...).ShouldPass().Out()
Expect(componentList).NotTo(ContainSubstring(cmpName))
files := helper.ListFilesInDir(commonVar.Context)
Expect(files).NotTo(ContainElement(".odo"))
})
It("should create a local python component and check for unsupported warning", func() {
helper.CopyExample(filepath.Join("source", "python"), commonVar.Context)
output := helper.Cmd("odo", append(args, "create", "--s2i", "python", cmpName, "--app", appName, "--project", commonVar.Project, "--context", commonVar.Context)...).ShouldPass().Out()
Expect(output).To(ContainSubstring("Warning: python is not fully supported by odo, and it is not guaranteed to work"))
})
It("should create a local nodejs component and check unsupported warning hasn't occurred", func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
output := helper.Cmd("odo", append(args, "create", "--s2i", "nodejs:latest", cmpName, "--app", appName, "--project", commonVar.Project, "--context", commonVar.Context)...).ShouldPass().Out()
Expect(output).NotTo(ContainSubstring("Warning"))
})
It("should create a local java component and check unsupported warning hasn't occurred", func() {
helper.CopyExample(filepath.Join("binary", "java", "openjdk"), commonVar.Context)
output := helper.Cmd("odo", append(args, "create", "--s2i", "java:latest", cmpName, "--project", commonVar.Project, "--context", commonVar.Context)...).ShouldPass().Out()
Expect(output).NotTo(ContainSubstring("Warning"))
})
// TODO: Fix later
XIt("should list out pushed components of different projects in json format along with path flag", func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.Cmd("odo", append(args, "create", "--s2i", "nodejs", "nodejs", "--project", commonVar.Project)...).ShouldPass()
info := helper.LocalEnvInfo(commonVar.Context)
Expect(info.GetApplication(), "app")
Expect(info.GetName(), "nodejs")
helper.Cmd("odo", append(args, "push")...).ShouldPass()
project2 := helper.CreateRandProject()
context2 := helper.CreateNewContext()
helper.Chdir(context2)
helper.CopyExample(filepath.Join("source", "python"), context2)
helper.Cmd("odo", append(args, "create", "--s2i", "python", "python", "--project", project2)...).ShouldPass()
info = helper.LocalEnvInfo(context2)
Expect(info.GetApplication(), "app")
Expect(info.GetName(), "python")
helper.Cmd("odo", append(args, "push")...).ShouldPass()
actual, err := helper.Unindented(helper.Cmd("odo", append(args, "list", "-o", "json", "--path", filepath.Dir(commonVar.Context))...).ShouldPass().Out())
Expect(err).Should(BeNil())
helper.Chdir(commonVar.Context)
helper.DeleteDir(context2)
helper.DeleteProject(project2)
// this orders the json
expected := fmt.Sprintf(`"metadata":{"name":"nodejs","namespace":"%s","creationTimestamp":null},"spec":{"app":"app","type":"nodejs","sourceType": "local","ports":["8080/TCP"]}`, commonVar.Project)
Expect(actual).Should(ContainSubstring(expected))
// this orders the json
expected = fmt.Sprintf(`"metadata":{"name":"python","namespace":"%s","creationTimestamp":null},"spec":{"app":"app","type":"python","sourceType": "local","ports":["8080/TCP"]}`, project2)
Expect(actual).Should(ContainSubstring(expected))
})
When("creating a named s2i nodejs component", func() {
BeforeEach(func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.Cmd("odo", append(args, "create", "--s2i", "nodejs", cmpName, "--project", commonVar.Project, "--context", commonVar.Context, "--app", appName)...).ShouldPass()
info := helper.LocalEnvInfo(commonVar.Context)
Expect(info.GetApplication(), appName)
Expect(info.GetName(), cmpName)
})
It("should set the correct component name, language and projectType in devfile metadata", func() {
metadata := helper.GetMetadataFromDevfile("devfile.yaml")
Expect(metadata.Name).To(BeEquivalentTo(cmpName))
Expect(metadata.Language).To(ContainSubstring("nodejs"))
Expect(metadata.ProjectType).To(ContainSubstring("nodejs"))
})
It("should list the component when it is not pushed", func() {
cmpList := helper.Cmd("odo", append(args, "list", "--context", commonVar.Context)...).ShouldPass().Out()
metadata := helper.GetMetadataFromDevfile("devfile.yaml")
helper.MatchAllInOutput(cmpList, []string{cmpName, "Not Pushed", metadata.ProjectType})
helper.Cmd("odo", append(args, "delete", "-f", "--all", "--context", commonVar.Context)...).ShouldPass()
})
XIt("should list the state as unknown for disconnected cluster", func() {
kubeconfigOrig := os.Getenv("KUBECONFIG")
unset := func() {
// KUBECONFIG defaults to ~/.kube/config so it can be empty in some cases.
if kubeconfigOrig != "" {
os.Setenv("KUBECONFIG", kubeconfigOrig)
} else {
os.Unsetenv("KUBECONFIG")
}
}
os.Setenv("KUBECONFIG", "/no/such/path")
defer unset()
cmpList := helper.Cmd("odo", append(args, "list", "--context", commonVar.Context, "--v", "9")...).ShouldPass().Out()
helper.MatchAllInOutput(cmpList, []string{cmpName, "Unknown"})
unset()
fmt.Printf("kubeconfig before delete %v", os.Getenv("KUBECONFIG"))
helper.Cmd("odo", append(args, "delete", "-f", "--all", "--context", commonVar.Context)...).ShouldPass()
})
It("should describe the component when it is not pushed", func() {
helper.Cmd("odo", "url", "create", "url-1", "--context", commonVar.Context).ShouldPass()
helper.Cmd("odo", "url", "create", "url-2", "--context", commonVar.Context).ShouldPass()
helper.Cmd("odo", "storage", "create", "storage-1", "--size", "1Gi", "--path", "/data1", "--context", commonVar.Context).ShouldPass()
cmpDescribe := helper.Cmd("odo", append(args, "describe", "--context", commonVar.Context)...).ShouldPass().Out()
metadata := helper.GetMetadataFromDevfile("devfile.yaml")
helper.MatchAllInOutput(cmpDescribe, []string{
cmpName,
metadata.ProjectType,
"url-1",
"url-2",
"storage-1",
})
})
It("should fail to create component twice from same directory", func() {
output := helper.Cmd("odo", append(args, "create", "--s2i", "nodejs", cmpName, "--project", commonVar.Project)...).ShouldFail().Err()
Expect(output).To(ContainSubstring("this directory already contains a component"))
})
When("odo push is executed", func() {
BeforeEach(func() {
helper.Cmd("odo", append(args, "push", "--context", commonVar.Context)...).ShouldPass()
})
It("should not list component even in new project with --project and --context at the same time", func() {
projectList := helper.Cmd("odo", "project", "list").ShouldPass().Out()
Expect(projectList).To(ContainSubstring(commonVar.Project))
helper.Cmd("odo", "list", "--project", commonVar.Project, "--context", commonVar.Context).ShouldFail()
})
It("should list the component", func() {
cmpList := helper.Cmd("odo", append(args, "list", "--project", commonVar.Project)...).ShouldPass().Out()
metadata := helper.GetMetadataFromDevfile("devfile.yaml")
Expect(cmpList).To(ContainSubstring(cmpName))
Expect(cmpList).To(ContainSubstring(metadata.ProjectType))
actualCompListJSON := helper.Cmd("odo", append(args, "list", "--project", commonVar.Project, "-o", "json")...).ShouldPass().Out()
valuesCList := gjson.GetMany(actualCompListJSON, "kind", "devfileComponents.0.kind", "devfileComponents.0.metadata.name", "devfileComponents.0.spec.app")
expectedCList := []string{"List", "Component", cmpName, appName}
Expect(helper.GjsonMatcher(valuesCList, expectedCList)).To(Equal(true))
cmpAllList := helper.Cmd("odo", append(args, "list", "--all-apps")...).ShouldPass().Out()
Expect(cmpAllList).To(ContainSubstring(cmpName))
})
It("should delete --all", func() {
helper.Cmd("odo", append(args, "delete", "--context", commonVar.Context, "-f", "--all")...).ShouldPass()
componentList := helper.Cmd("odo", append(args, "list", "--app", appName, "--project", commonVar.Project)...).ShouldPass().Out()
Expect(componentList).NotTo(ContainSubstring(cmpName))
files := helper.ListFilesInDir(commonVar.Context)
Expect(files).NotTo(ContainElement(".odo"))
})
})
})
When("creating an s2i nodejs component with context .", func() {
BeforeEach(func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.Cmd("odo", append(args, "create", "--s2i", "nodejs", "--project", commonVar.Project, "--context", ".", "--app", appName)...).ShouldPass()
})
It("should create default named component when passed same context differently", func() {
dir := filepath.Base(commonVar.Context)
componentName := helper.GetLocalEnvInfoValueWithContext("Name", commonVar.Context)
Expect(componentName).To(ContainSubstring("nodejs"))
Expect(componentName).To(ContainSubstring(dir))
info := helper.LocalEnvInfo(commonVar.Context)
Expect(info.GetApplication(), appName)
Expect(info.GetName(), componentName)
helper.DeleteDir(filepath.Join(commonVar.Context, ".odo"))
helper.Cmd("odo", append(args, "create", "--s2i", "nodejs", "--project", commonVar.Project, "--context", commonVar.Context, "--app", appName)...).ShouldPass()
newComponentName := helper.GetLocalEnvInfoValueWithContext("Name", commonVar.Context)
Expect(newComponentName).To(ContainSubstring("nodejs"))
Expect(newComponentName).To(ContainSubstring(dir))
})
})
When("a binary is copied in the current directory", func() {
BeforeEach(func() {
oc.ImportJavaIS(commonVar.Project)
helper.CopyExample(filepath.Join("binary", "java", "openjdk"), commonVar.Context)
})
It("should not fail when --context is not set", func() {
binaryFilePath := filepath.Join(commonVar.Context, "sb.jar")
if runtime.GOOS == "darwin" {
binaryFilePath = filepath.Join("/private", binaryFilePath)
}
helper.Cmd("odo", append(args, "create", "--s2i", "java:8", cmpName, "--project",
commonVar.Project, "--binary", binaryFilePath)...).ShouldPass()
info := helper.LocalEnvInfo(commonVar.Context)
Expect(info.GetName(), cmpName)
})
It("should fail when --binary is not in --context folder", func() {
newContext := helper.CreateNewContext()
defer helper.DeleteDir(newContext)
output := helper.Cmd("odo", append(args, "create", "--s2i", "java:8", cmpName, "--project",
commonVar.Project, "--binary", filepath.Join(commonVar.Context, "sb.jar"), "--context", newContext)...).ShouldFail().Err()
Expect(output).To(ContainSubstring("inside of the context directory"))
})
It("should be valid if path is relative and includes ../", func() {
relativeContext := fmt.Sprintf("..%c%s", filepath.Separator, filepath.Base(commonVar.Context))
binaryFilePath := filepath.Join(commonVar.Context, "sb.jar")
if runtime.GOOS == "darwin" {
binaryFilePath = filepath.Join("/private", binaryFilePath)
}
helper.Cmd("odo", append(args, "create", "--s2i", "java:8", cmpName, "--project",
commonVar.Project, "--binary", binaryFilePath, "--context", relativeContext)...).ShouldPass()
info := helper.LocalEnvInfo(relativeContext)
Expect(info.GetApplication(), "app")
Expect(info.GetName(), cmpName)
})
})
})
When("creating an s2i component", func() {
BeforeEach(func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.Cmd("odo", append(args, "create", "--s2i", "nodejs", cmpNameDefault, "--app", appName, "--project", commonVar.Project, "--context", commonVar.Context)...).ShouldPass()
info := helper.LocalEnvInfo(commonVar.Context)
Expect(info.GetApplication(), appName)
Expect(info.GetName(), cmpNameDefault)
})
It("should pass inside a odo directory without component name as parameter", func() {
helper.Cmd("odo", "url", "create", "example", "--context", commonVar.Context).ShouldPass()
helper.Cmd("odo", append(args, "push", "--context", commonVar.Context)...).ShouldPass()
// changing directory to the context directory
helper.Chdir(commonVar.Context)
cmpListOutput := helper.Cmd("odo", append(args, "list")...).ShouldPass().Out()
Expect(cmpListOutput).To(ContainSubstring(cmpNameDefault))
cmpDescribe := helper.Cmd("odo", append(args, "describe")...).ShouldPass().Out()
helper.MatchAllInOutput(cmpDescribe, []string{cmpNameDefault, "nodejs"})
url := helper.DetermineRouteURL(commonVar.Context)
Expect(cmpDescribe).To(ContainSubstring(url))
helper.Cmd("odo", append(args, "delete", "-f")...).ShouldPass()
})
It("should fail outside a odo directory without component name as parameter", func() {
helper.Cmd("odo", append(args, "push", "--context", commonVar.Context)...).ShouldPass()
// commands should fail as the component name is missing
helper.Cmd("odo", append(args, "describe", "--app", appName, "--project", commonVar.Project)...).ShouldFail()
helper.Cmd("odo", append(args, "delete", "-f", "--app", appName, "--project", commonVar.Project)...).ShouldFail()
})
})
When("creating a named s2i component with urls and storages", func() {
BeforeEach(func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.Cmd("odo", append(args, "create", "--s2i", "nodejs", cmpName, "--app", appName, "--project", commonVar.Project, "--context", commonVar.Context)...).ShouldPass()
info := helper.LocalEnvInfo(commonVar.Context)
Expect(info.GetApplication(), appName)
Expect(info.GetName(), cmpName)
helper.Cmd("odo", "url", "create", "example-1", "--context", commonVar.Context).ShouldPass()
helper.Cmd("odo", "storage", "create", "storage-1", "--size", "1Gi", "--path", "/data1", "--context", commonVar.Context).ShouldPass()
helper.Cmd("odo", append(args, "push", "--context", commonVar.Context)...).ShouldPass()
helper.Cmd("odo", "url", "create", "example-2", "--context", commonVar.Context).ShouldPass()
helper.Cmd("odo", "storage", "create", "storage-2", "--size", "1Gi", "--path", "/data2", "--context", commonVar.Context).ShouldPass()
helper.Cmd("odo", append(args, "push", "--context", commonVar.Context)...).ShouldPass()
})
It("should delete the component and the owned resources", func() {
helper.Cmd("odo", append(args, "delete", "-f", "--context", commonVar.Context)...).ShouldPass()
oc.WaitAndCheckForExistence("routes", commonVar.Project, 1)
oc.WaitAndCheckForExistence("dc", commonVar.Project, 1)
oc.WaitAndCheckForExistence("pvc", commonVar.Project, 1)
oc.WaitAndCheckForExistence("bc", commonVar.Project, 1)
oc.WaitAndCheckForExistence("is", commonVar.Project, 1)
oc.WaitAndCheckForExistence("service", commonVar.Project, 1)
})
It("should delete the component and the owned resources with wait flag", func() {
// delete with --wait flag
helper.Cmd("odo", append(args, "delete", "-f", "-w", "--context", commonVar.Context)...).ShouldPass()
helper.VerifyResourcesDeleted(oc, []helper.ResourceInfo{
{
ResourceType: helper.ResourceTypeRoute,
ResourceName: "example",
Namespace: commonVar.Project,
},
{
ResourceType: helper.ResourceTypeService,
ResourceName: "example",
Namespace: commonVar.Project,
},
{
// verify s2i pvc is delete
ResourceType: helper.ResourceTypePVC,
ResourceName: "s2idata",
Namespace: commonVar.Project,
},
{
ResourceType: helper.ResourceTypePVC,
ResourceName: "storage-1",
Namespace: commonVar.Project,
},
{
ResourceType: helper.ResourceTypePVC,
ResourceName: "storage-2",
Namespace: commonVar.Project,
},
{
ResourceType: helper.ResourceTypeDeploymentConfig,
ResourceName: cmpName,
Namespace: commonVar.Project,
},
})
})
})
When("creating a component with a numeric named context", func() {
var contextNumeric string
BeforeEach(func() {
var err error
ts := time.Now().UnixNano()
contextNumeric, err = ioutil.TempDir("", fmt.Sprint(ts))
Expect(err).ToNot(HaveOccurred())
})
AfterEach(func() {
helper.DeleteDir(contextNumeric)
})
It("should create default named component in a directory with numeric name", func() {
helper.CopyExample(filepath.Join("source", "nodejs"), contextNumeric)
helper.Cmd("odo", append(args, "create", "--s2i", "nodejs", "--project", commonVar.Project, "--context", contextNumeric, "--app", appName)...).ShouldPass()
info := helper.LocalEnvInfo(contextNumeric)
Expect(info.GetApplication(), appName)
helper.Cmd("odo", append(args, "push", "--context", contextNumeric, "-v4")...).ShouldPass()
})
})
When("creating a component using symlink", func() {
var symLinkPath string
BeforeEach(func() {
if runtime.GOOS == "windows" {
Skip("Skipping test because for symlink creation on platform like Windows, go library needs elevated privileges.")
}
// create a symlink
symLinkName := helper.RandString(10)
helper.CreateSymLink(commonVar.Context, filepath.Join(filepath.Dir(commonVar.Context), symLinkName))
symLinkPath = filepath.Join(filepath.Dir(commonVar.Context), symLinkName)
})
AfterEach(func() {
// remove the symlink
err := os.Remove(symLinkPath)
Expect(err).NotTo(HaveOccurred())
})
It("should be able to deploy a spring boot uberjar file using symlinks in all odo commands", func() {
oc.ImportJavaIS(commonVar.Project)
helper.CopyExample(filepath.Join("binary", "java", "openjdk"), commonVar.Context)
// create the component using symlink
helper.Cmd("odo", append(args, "create", "--s2i", "java:8", cmpName, "--project",
commonVar.Project, "--binary", filepath.Join(symLinkPath, "sb.jar"), "--context", symLinkPath)...).ShouldPass()
// Create a URL and push without using the symlink
helper.Cmd("odo", "url", "create", "uberjaropenjdk", "--port", "8080", "--context", symLinkPath).ShouldPass()
info := helper.LocalEnvInfo(symLinkPath)
Expect(info.GetApplication(), "app")
Expect(info.GetName(), cmpName)
helper.Cmd("odo", append(args, "push", "--context", symLinkPath)...).ShouldPass()
routeURL := helper.DetermineRouteURL(symLinkPath)
// Ping said URL
helper.HttpWaitFor(routeURL, "HTTP Booster", 300, 1)
// Delete the component
helper.Cmd("odo", append(args, "delete", "-f", "--context", symLinkPath)...).ShouldPass()
})
It("should be able to deploy a wildfly war file using symlinks in some odo commands", func() {
helper.CopyExample(filepath.Join("binary", "java", "wildfly"), commonVar.Context)
helper.Cmd("odo", append(args, "create", "--s2i", "wildfly", cmpName, "--project",
commonVar.Project, "--binary", filepath.Join(symLinkPath, "ROOT.war"), "--context", symLinkPath)...).ShouldPass()
// Create a URL
helper.Cmd("odo", "url", "create", "warfile", "--port", "8080", "--context", commonVar.Context).ShouldPass()
info := helper.LocalEnvInfo(commonVar.Context)
Expect(info.GetApplication(), "app")
Expect(info.GetName(), cmpName)
helper.Cmd("odo", append(args, "push", "--context", commonVar.Context)...).ShouldPass()
routeURL := helper.DetermineRouteURL(commonVar.Context)
// Ping said URL
helper.HttpWaitFor(routeURL, "Sample", 90, 1)
// Delete the component
helper.Cmd("odo", append(args, "delete", "-f", "--context", commonVar.Context)...).ShouldPass()
})
})
Context("convert s2i to devfile", func() {
BeforeEach(func() {
os.Setenv("ODO_EXPERIMENTAL", "true")
})
AfterEach(func() {
os.Unsetenv("ODO_EXPERIMENTAL")
})
It("should convert s2i component to devfile component successfully", func() {
urlName := "url1"
storageName := "storage1"
// create a s2i component using --s2i that generates a devfile
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.Cmd("odo", "component", "create", "--s2i", "nodejs", cmpName, "--project", commonVar.Project, "--context", commonVar.Context, "--app", appName).ShouldPass()
helper.Cmd("odo", "url", "create", urlName, "--port", "8080", "--context", commonVar.Context).ShouldPass()
helper.Cmd("odo", "storage", "create", storageName, "--path", "/data1", "--size", "1Gi", "--context", commonVar.Context).ShouldPass()
helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass()
// check the status of devfile component
stdout := helper.Cmd("odo", "list", "--context", commonVar.Context).ShouldPass().Out()
helper.MatchAllInOutput(stdout, []string{cmpName, "Pushed"})
// verify the url
stdout = helper.Cmd("odo", "url", "list", "--context", commonVar.Context).ShouldPass().Out()
helper.MatchAllInOutput(stdout, []string{urlName, "Pushed", "false", "route"})
//verify storage
stdout = helper.Cmd("odo", "storage", "list", "--context", commonVar.Context).ShouldPass().Out()
helper.MatchAllInOutput(stdout, []string{storageName, "Pushed"})
})
})
When("components are not created/managed by odo", func() {
var runner helper.CliRunner
type compStruct struct {
App, Name string
}
// This array will contain static data taken from tests/examples/manifests/dc-label.yaml and
// tests/examples/manifests/deployment-httpd-label.yaml, tests/examples/manifests/deployment-app-label.yaml.
// If this test breaks, check if the data here matches with that of the manifest files
var compList = []compStruct{
{"app", "example-deployment"},
}
BeforeEach(func() {
// Create resources that are not managed by odo
runner = helper.GetCliRunner()
dfile := filepath.Join(commonVar.Context, "deployment-app-label.yaml")
helper.CopyManifestFile("deployment-app-label.yaml", dfile)
runner.Run("apply", "-f", dfile).Wait()
// if it is openshift env, we also deploy the deploymentconfig yaml
if !helper.IsKubernetesCluster() {
dcfile := filepath.Join(commonVar.Context, "dc-label.yaml")
helper.CopyManifestFile("dc-label.yaml", dcfile)
runner.Run("apply", "-f", dcfile).Wait()
compList = append(compList, compStruct{"app", "example-dc"})
}
})
// verifyListOutput verifies if the components not managed by odo are listed
var verifyListOutput = func(output string, componentList []compStruct) {
helper.MatchAllInOutput(output, []string{"MANAGED BY ODO", "No"})
for _, comp := range componentList {
Expect(output).To(ContainSubstring(comp.Name))
Expect(output).To(ContainSubstring(comp.App))
}
}
It("should list the components", func() {
output := helper.Cmd("odo", append(args, "list")...).ShouldPass().Out()
verifyListOutput(output, compList)
})
When("the component has a different app name than the default 'app'", func() {
BeforeEach(func() {
// Create resources that are not managed by odo
dfile := filepath.Join(commonVar.Context, "deployment-httpd-label.yaml")
helper.CopyManifestFile("deployment-httpd-label.yaml", dfile)
runner.Run("apply", "-f", dfile).Wait()
})
It("should list the components with --all-apps flag", func() {
output := helper.Cmd("odo", append(args, "list", "--all-apps")...).ShouldPass().Out()
verifyListOutput(output, append(compList, compStruct{"httpd", "example-deployment-httpd"}))
})
It("should list the components with --app flag", func() {
output := helper.Cmd("odo", append(args, "list", "--app", "httpd")...).ShouldPass().Out()
verifyListOutput(output, []compStruct{{"httpd", "example-deployment-httpd"}})
})
})
It("should list the components in json format with -o json flag", func() {
output := helper.Cmd("odo", append(args, "list", "--project", commonVar.Project, "-o", "json")...).ShouldPass().Out()
for _, comp := range compList {
valuesCList := gjson.GetMany(output, "kind", "otherComponents.#.kind", "otherComponents.#.metadata.name", "otherComponents.#.spec.app")
expectedCList := []string{"List", "Component", comp.Name, comp.App}
Expect(helper.GjsonMatcher(valuesCList, expectedCList)).To(Equal(true))
}
})
When("executing odo list from other project", func() {
var otherProject string
BeforeEach(func() {
otherProject = commonVar.CliRunner.CreateRandNamespaceProject()
})
AfterEach(func() {
helper.Cmd("odo", "project", "set", commonVar.Project).ShouldPass()
commonVar.CliRunner.DeleteNamespaceProject(otherProject)
})
It("should list the components with --project flag", func() {
output := helper.Cmd("odo", append(args, "list", "--project", commonVar.Project)...).ShouldPass().Out()
verifyListOutput(output, compList)
})
})
})
}

View File

@@ -1,86 +0,0 @@
package debug
import (
"path/filepath"
"strconv"
"strings"
"time"
"github.com/openshift/odo/pkg/config"
"github.com/openshift/odo/pkg/testingutil"
"github.com/openshift/odo/tests/helper"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
// since during parallel runs of cmd debug, the port might be occupied by the other tests
// we execute these tests serially
var _ = Describe("odo debug command serial tests", func() {
var commonVar helper.CommonVar
// This is run before every Spec (It)
var _ = BeforeEach(func() {
commonVar = helper.CommonBeforeEach()
})
// Clean up after the test
// This is run after every Spec (It)
var _ = AfterEach(func() {
helper.CommonAfterEach(commonVar)
})
It("should auto-select a local debug port when the given local port is occupied", func() {
projName := helper.GetCliRunner().CreateRandNamespaceProjectOfLength(5)
defer func() {
helper.GetCliRunner().DeleteNamespaceProject(projName)
}()
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.Cmd("odo", "component", "create", "--s2i", "nodejs:latest", "nodejs-cmp", "--project", projName, "--context", commonVar.Context).ShouldPass()
helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass()
stopChannel := make(chan bool)
go func() {
helper.Cmd("odo", "debug", "port-forward", "--context", commonVar.Context).WithTerminate(60*time.Second, stopChannel).ShouldRun()
}()
stopListenerChan := make(chan bool)
startListenerChan := make(chan bool)
listenerStarted := false
go func() {
err := testingutil.FakePortListener(startListenerChan, stopListenerChan, config.DefaultDebugPort)
if err != nil {
close(startListenerChan)
Expect(err).Should(BeNil())
}
}()
// wait for the test server to start listening
if <-startListenerChan {
listenerStarted = true
}
freePort := ""
helper.WaitForCmdOut("odo", []string{"debug", "info", "--context", commonVar.Context}, 1, false, func(output string) bool {
if strings.Contains(output, "Debug is running") {
splits := strings.SplitN(output, ":", 2)
Expect(len(splits)).To(Equal(2))
freePort = strings.TrimSpace(splits[1])
_, err := strconv.Atoi(freePort)
Expect(err).NotTo(HaveOccurred())
return true
}
return false
})
// 400 response expected because the endpoint expects a websocket request and we are doing a HTTP GET
// We are just using this to validate if nodejs agent is listening on the other side
helper.HttpWaitForWithStatus("http://localhost:"+freePort, "WebSockets request was expected", 12, 5, 400)
stopChannel <- true
if listenerStarted == true {
stopListenerChan <- true
} else {
close(stopListenerChan)
}
})
})

View File

@@ -1,11 +0,0 @@
package debug
import (
"testing"
"github.com/openshift/odo/tests/helper"
)
func TestDebug(t *testing.T) {
helper.RunTestSpecs(t, "Debug Suite")
}

View File

@@ -1,7 +1,7 @@
package devfile
import (
"os"
"github.com/tidwall/gjson"
"path/filepath"
. "github.com/onsi/ginkgo"
@@ -25,6 +25,35 @@ var _ = Describe("odo devfile app command tests", func() {
helper.CommonAfterEach(commonVar)
})
It("should display the help for app command", func() {
appHelp := helper.Cmd("odo", "app", "-h").ShouldPass().Out()
// Trimmed the end of the message string to make it compatible across clusters
Expect(appHelp).To(ContainSubstring("Performs application operations related to"))
})
Context("on a fresh new project", func() {
BeforeEach(func() {
appList := helper.Cmd("odo", "app", "list", "--project", commonVar.Project).ShouldPass().Out()
Expect(appList).To(ContainSubstring("There are no applications deployed"))
actual := helper.Cmd("odo", "app", "list", "-o", "json", "--project", commonVar.Project).ShouldPass().Out()
values := gjson.GetMany(actual, "kind", "metadata", "items")
expected := []string{"List", "{}", "[]"}
Expect(helper.GjsonMatcher(values, expected)).To(Equal(true))
})
It("should fail deleting non existing app", func() {
appDelete := helper.Cmd("odo", "app", "delete", "test", "--project", commonVar.Project, "-f").ShouldFail().Err()
Expect(appDelete).To(ContainSubstring("test app does not exists"))
})
It("should fail describing non existing app", func() {
appDescribe := helper.Cmd("odo", "app", "describe", "test", "--project", commonVar.Project).ShouldFail().Err()
Expect(appDescribe).To(ContainSubstring("test app does not exists"))
})
})
When("the user creates and pushes two new devfile components in different apps", func() {
var context0 string
var context1 string
@@ -57,47 +86,6 @@ var _ = Describe("odo devfile app command tests", func() {
helper.DeleteDir(context1)
})
When("the user creates and pushes a third s2i component on a openshift cluster", func() {
var context00 string
var info testInfo
BeforeEach(func() {
if os.Getenv("KUBERNETES") == "true" {
Skip("This is a OpenShift specific scenario, skipping")
}
context00 = helper.CreateNewContext()
component00 := helper.RandString(4)
storage00 := helper.RandString(4)
url00 := helper.RandString(4)
helper.CopyExample(filepath.Join("source", "nodejs"), context00)
helper.Cmd("odo", "component", "create", "--s2i", "nodejs", component00, "--app", app0, "--project", namespace, "--context", context00).ShouldPass()
helper.Cmd("odo", "storage", "create", storage00, "--path", "/data", "--size", "1Gi", "--context", context00).ShouldPass()
helper.Cmd("odo", "url", "create", url00, "--port", "8080", "--context", context00).ShouldPass()
helper.Cmd("odo", "push", "--context", context00).ShouldPass()
info = testInfo{
app0: app0,
app1: app1,
comp0: component0,
comp00: component00,
url00: url00,
storage00: storage00,
namespace: namespace,
}
})
AfterEach(func() {
helper.Cmd("odo", "delete", "-f", "--context", context00).ShouldPass()
helper.DeleteDir(context00)
})
It("should list, describe and delete the app properly with json output", func() {
runner(info)
})
})
When("the user creates and pushes a third devfile component", func() {
var context00 string

View File

@@ -1,7 +1,6 @@
package devfile
import (
"encoding/json"
"os"
"path"
"path/filepath"
@@ -59,12 +58,7 @@ var _ = Describe("odo devfile create command tests", func() {
It("should fail to create the devfile component with invalid component type", func() {
fakeComponentName := "fake-component"
output := helper.Cmd("odo", "create", fakeComponentName).ShouldFail().Err()
var expectedString string
if os.Getenv("KUBERNETES") == "true" {
expectedString = "component type not found"
} else {
expectedString = "component type \"" + fakeComponentName + "\" not found"
}
expectedString := "component type \"" + fakeComponentName + "\" is not supported"
helper.MatchAllInOutput(output, []string{expectedString})
})
})
@@ -218,10 +212,10 @@ var _ = Describe("odo devfile create command tests", func() {
}
})
It("should fail when we create the devfile or s2i component multiple times", func() {
It("should fail when we create the devfile", func() {
helper.CopyExampleDevFile(filepath.Join("source", "devfiles", "nodejs", devfile), filepath.Join(commonVar.Context, devfile))
helper.Cmd("odo", "create", "nodejs").ShouldPass()
output := helper.Cmd("odo", "create", "nodejs", "--s2i").ShouldFail().Err()
output := helper.Cmd("odo", "create", "nodejs").ShouldFail().Err()
Expect(output).To(ContainSubstring("this directory already contains a component"))
})
})
@@ -367,66 +361,6 @@ var _ = Describe("odo devfile create command tests", func() {
helper.DeleteDir(context2)
})
Context("When executing odo create with --s2i flag", func() {
var newContext string
JustBeforeEach(func() {
newContext = path.Join(commonVar.Context, "newContext")
devfilePath = filepath.Join(newContext, devfile)
helper.MakeDir(newContext)
helper.CopyExampleDevFile(filepath.Join("source", "devfiles", "nodejs", devfile), devfilePath)
})
JustAfterEach(func() {
helper.DeleteDir(newContext)
})
It("should fail to create the devfile component which doesn't have an s2i component of same name", func() {
componentName := helper.RandString(6)
output := helper.Cmd("odo", "catalog", "list", "components", "-o", "json").ShouldPass().Out()
wantOutput := []string{"java-openliberty"}
var data map[string]interface{}
err := json.Unmarshal([]byte(output), &data)
if err != nil {
Expect(err).Should(BeNil())
}
outputBytes, err := json.Marshal(data["s2iItems"])
if err == nil {
output = string(outputBytes)
}
helper.DontMatchAllInOutput(output, wantOutput)
outputBytes, err = json.Marshal(data["devfileItems"])
if err == nil {
output = string(outputBytes)
}
helper.MatchAllInOutput(output, wantOutput)
helper.Cmd("odo", "create", "java-openliberty", componentName, "--s2i").ShouldFail().Err()
})
It("should fail to create the devfile component with valid file system path", func() {
output := helper.Cmd("odo", "create", "nodejs", "--s2i", "--devfile", devfilePath).ShouldFail().Err()
helper.MatchAllInOutput(output, []string{"you can't set --s2i flag as true if you want to use the devfile via --devfile flag"})
})
It("should fail to create the component specified with valid project and download the source", func() {
output := helper.Cmd("odo", "create", "nodejs", "--starter=nodejs-starter", "--s2i").ShouldFail().Err()
helper.MatchAllInOutput(output, []string{"you can't set --s2i flag as true if you want to use the starter via --starter flag"})
})
It("should fail to create the devfile component with --registry specified", func() {
output := helper.Cmd("odo", "create", "nodejs", "--registry", "DefaultDevfileRegistry", "--s2i").ShouldFail().Err()
helper.MatchAllInOutput(output, []string{"you can't set --s2i flag as true if you want to use the registry via --registry flag"})
})
})
// Currently these tests need interactive mode in order to set the name of the component.
// Once this feature is added we can change these tests.
//Context("When executing odo create with devfile component and --downloadSource flag with github type", func() {

View File

@@ -47,7 +47,7 @@ var _ = Describe("odo devfile url command tests", func() {
Expect(stdout).To(ContainSubstring("host must be provided"))
stdout = helper.Cmd("odo", "url", "create", url1, "--port", "3000", "--host", host, "--ingress").ShouldFail().Err()
Expect(stdout).To(ContainSubstring("The current directory does not represent an odo component"))
Expect(stdout).To(ContainSubstring("the current directory does not represent an odo component"))
helper.Cmd("odo", "url", "create", url1, "--port", "3000", "--host", host, "--ingress", "--context", subFolderContext).ShouldPass()
helper.Cmd("odo", "url", "create", url2, "--port", "3000", "--host", host, "--ingress", "--context", subFolderContext).ShouldPass()
stdout = helper.Cmd("odo", "push", "--context", subFolderContext).ShouldPass().Out()

View File

@@ -67,7 +67,7 @@ var _ = Describe("odo devfile watch command tests", func() {
StringsToBeMatched: []string{"Executing devbuild command", "Executing devrun command"},
}
// odo watch and validate
utils.OdoWatch(utils.OdoV1Watch{}, odoV2Watch, commonVar.Project, commonVar.Context, watchFlag, commonVar.CliRunner, "kube")
utils.OdoWatch(odoV2Watch, commonVar.Project, commonVar.Context, watchFlag, commonVar.CliRunner, "kube")
})
})
@@ -87,7 +87,7 @@ var _ = Describe("odo devfile watch command tests", func() {
StringsToBeMatched: []string{"Executing build command", "Executing run command"},
}
// odo watch and validate
utils.OdoWatch(utils.OdoV1Watch{}, odoV2Watch, commonVar.Project, commonVar.Context, watchFlag, commonVar.CliRunner, "kube")
utils.OdoWatch(odoV2Watch, commonVar.Project, commonVar.Context, watchFlag, commonVar.CliRunner, "kube")
})
})
@@ -160,7 +160,7 @@ var _ = Describe("odo devfile watch command tests", func() {
StringsToBeMatched: []string{"Executing devbuild command", "Executing devrun command"},
}
// odo watch and validate
utils.OdoWatch(utils.OdoV1Watch{}, odoV2Watch, commonVar.Project, commonVar.Context, watchFlag, commonVar.CliRunner, "kube")
utils.OdoWatch(odoV2Watch, commonVar.Project, commonVar.Context, watchFlag, commonVar.CliRunner, "kube")
})
})
@@ -201,7 +201,7 @@ var _ = Describe("odo devfile watch command tests", func() {
CmpName: cmpName,
StringsToBeMatched: []string{"Executing devbuild command", "Executing devrun command"},
}
utils.OdoWatch(utils.OdoV1Watch{}, odoV2Watch, commonVar.Project, commonVar.Context, watchFlag, commonVar.CliRunner, "kube")
utils.OdoWatch(odoV2Watch, commonVar.Project, commonVar.Context, watchFlag, commonVar.CliRunner, "kube")
// check that the --debug-command fails when the component is not pushed using debug mode
output = helper.Cmd("odo", "watch", "--debug-command", "debug").WithRetry(1, 1).ShouldFail().Err()

View File

@@ -6,7 +6,6 @@ import (
"index/suffixarray"
"os"
"path/filepath"
"reflect"
"strconv"
"strings"
"time"
@@ -19,12 +18,6 @@ import (
. "github.com/onsi/gomega"
)
type OdoV1Watch struct {
SrcType string
RouteURL string
AppName string
}
type OdoV2Watch struct {
CmpName string
StringsToBeMatched []string
@@ -34,16 +27,9 @@ type OdoV2Watch struct {
}
// OdoWatch creates files, dir in the context and watches for the changes to be pushed
// Specify OdoV1Watch for odo version 1, OdoV2Watch for odo version 2(devfile)
// Specify OdoV2Watch for odo version 2(devfile)
// platform is kube
func OdoWatch(odoV1Watch OdoV1Watch, odoV2Watch OdoV2Watch, project, context, flag string, runner interface{}, platform string) {
isDevfileTest := false
// if the odoV2Watch object is not empty, its a devfile test
if !reflect.DeepEqual(odoV2Watch, OdoV2Watch{}) {
isDevfileTest = true
}
func OdoWatch(odoV2Watch OdoV2Watch, project, context, flag string, runner interface{}, platform string) {
// After the watch command has started (indicated via channel), simulate file system changes
startSimulationCh := make(chan bool)
@@ -59,27 +45,15 @@ func OdoWatch(odoV1Watch OdoV1Watch, odoV2Watch OdoV2Watch, project, context, fl
_, err = os.Create(filepath.Join(context, "a.txt"))
Expect(err).To(BeNil())
if isDevfileTest {
if odoV2Watch.SrcType == "openjdk" {
helper.ReplaceString(filepath.Join(context, "src", "main", "java", "MessageProducer.java"), "Hello", "Hello odo")
} else {
helper.ReplaceString(filepath.Join(context, "server.js"), "Hello", "Hello odo")
}
if odoV2Watch.SrcType == "openjdk" {
helper.ReplaceString(filepath.Join(context, "src", "main", "java", "MessageProducer.java"), "Hello", "Hello odo")
} else {
helper.DeleteDir(filepath.Join(context, "abcd"))
if odoV1Watch.SrcType == "openjdk" {
helper.ReplaceString(filepath.Join(context, "src", "main", "java", "MessageProducer.java"), "Hello", "Hello odo")
} else {
helper.ReplaceString(filepath.Join(context, "server.js"), "Hello", "Hello odo")
}
helper.ReplaceString(filepath.Join(context, "server.js"), "Hello", "Hello odo")
}
}
}()
if !isDevfileTest {
flag = strings.TrimSpace(fmt.Sprintf("-v 4 %s", flag))
}
success, err := helper.WatchNonRetCmdStdOut(
("odo watch " + flag + " --context " + context),
time.Duration(5)*time.Minute,
@@ -90,41 +64,32 @@ func OdoWatch(odoV1Watch OdoV1Watch, odoV2Watch OdoV2Watch, project, context, fl
return true
}
// Returns true if the test has succeeded, false if not yet
if isDevfileTest {
stringsMatched := true
for _, stringToBeMatched := range odoV2Watch.StringsToBeMatched {
if !strings.Contains(output, stringToBeMatched) {
fmt.Fprintln(GinkgoWriter, "Missing string: ", stringToBeMatched)
stringsMatched = false
}
stringsMatched := true
for _, stringToBeMatched := range odoV2Watch.StringsToBeMatched {
if !strings.Contains(output, stringToBeMatched) {
fmt.Fprintln(GinkgoWriter, "Missing string: ", stringToBeMatched)
stringsMatched = false
}
}
if stringsMatched {
if stringsMatched {
// first push is successful
// now delete a folder and check if the deletion is propagated properly
// and the file is removed from the cluster
index := suffixarray.New([]byte(output))
offsets := index.Lookup([]byte(filepath.Join(context, "abcd")+" changed"), -1)
// first push is successful
// now delete a folder and check if the deletion is propagated properly
// and the file is removed from the cluster
index := suffixarray.New([]byte(output))
offsets := index.Lookup([]byte(filepath.Join(context, "abcd")+" changed"), -1)
// the first occurrence of '<target-dir> changed' means the creation of it was pushed to the cluster
// and the first push was successful
if len(offsets) == 1 {
helper.DeleteDir(filepath.Join(context, "abcd"))
} else if len(offsets) > 1 {
// the occurrence of 'target-directory' more than once indicates that the deletion was propagated too
// Verify directory deleted from component pod
err := validateContainerExecListDir(odoV1Watch, odoV2Watch, runner, platform, project, isDevfileTest)
Expect(err).To(BeNil())
return true
}
}
} else {
curlURL := helper.Cmd("curl", odoV1Watch.RouteURL).ShouldPass().Out()
if strings.Contains(curlURL, "Hello odo") {
// Verify delete from component pod
err := validateContainerExecListDir(odoV1Watch, odoV2Watch, runner, platform, project, isDevfileTest)
// the first occurrence of '<target-dir> changed' means the creation of it was pushed to the cluster
// and the first push was successful
if len(offsets) == 1 {
helper.DeleteDir(filepath.Join(context, "abcd"))
} else if len(offsets) > 1 {
// the occurrence of 'target-directory' more than once indicates that the deletion was propagated too
// Verify directory deleted from component pod
err := validateContainerExecListDir(odoV2Watch, runner, platform, project)
Expect(err).To(BeNil())
return true
}
@@ -140,14 +105,6 @@ func OdoWatch(odoV1Watch OdoV1Watch, odoV2Watch OdoV2Watch, project, context, fl
Expect(success).To(Equal(true))
Expect(err).To(BeNil())
if !isDevfileTest {
// Verify memory limits to be same as configured
getMemoryLimit := runner.(helper.OcRunner).MaxMemory(odoV1Watch.SrcType+"-app", odoV1Watch.AppName, project)
Expect(getMemoryLimit).To(ContainSubstring("700Mi"))
getMemoryRequest := runner.(helper.OcRunner).MinMemory(odoV1Watch.SrcType+"-app", odoV1Watch.AppName, project)
Expect(getMemoryRequest).To(ContainSubstring("400Mi"))
}
}
// OdoWatchWithDebug changes files in the context and watches for the changes to be pushed
@@ -254,25 +211,17 @@ func OdoWatchWithIgnore(odoV2Watch OdoV2Watch, context, flag string) {
Expect(err).To(BeNil())
}
func validateContainerExecListDir(odoV1Watch OdoV1Watch, odoV2Watch OdoV2Watch, runner interface{}, platform, project string, isDevfileTest bool) error {
func validateContainerExecListDir(odoV2Watch OdoV2Watch, runner interface{}, platform, project string) error {
var folderToCheck, podName string
cliRunner := runner.(helper.CliRunner)
switch platform {
case "kube":
if isDevfileTest {
folderToCheck = "/projects"
if odoV2Watch.FolderToCheck != "" {
folderToCheck = odoV2Watch.FolderToCheck
}
podName = cliRunner.GetRunningPodNameByComponent(odoV2Watch.CmpName, project)
} else {
ocRunner := runner.(helper.OcRunner)
podName = ocRunner.GetRunningPodNameOfComp(odoV1Watch.SrcType+"-app", project)
envs := ocRunner.GetEnvs(odoV1Watch.SrcType+"-app", odoV1Watch.AppName, project)
dir := envs["ODO_S2I_SRC_BIN_PATH"]
folderToCheck = filepath.ToSlash(filepath.Join(dir, "src"))
folderToCheck = "/projects"
if odoV2Watch.FolderToCheck != "" {
folderToCheck = odoV2Watch.FolderToCheck
}
podName = cliRunner.GetRunningPodNameByComponent(odoV2Watch.CmpName, project)
default:
return fmt.Errorf("Platform %s is not supported", platform)
}
@@ -298,7 +247,7 @@ func DeleteLocalConfig(args ...string) {
}
// VerifyCatalogListComponent verifies components inside wantOutput exists or not
// in both S2I Component list and Devfile Component list
// in Devfile Component list
func VerifyCatalogListComponent(output string, cmpName []string) error {
var data map[string]interface{}
listItems := []string{"devfileItems"}
@@ -307,10 +256,6 @@ func VerifyCatalogListComponent(output string, cmpName []string) error {
return err
}
if os.Getenv("KUBERNETES") != "true" {
listItems = append(listItems, "s2iItems")
}
for _, items := range listItems {
outputBytes, err := json.Marshal(data[items])
if err != nil {

View File

@@ -1,7 +1,6 @@
package integration
import (
"path/filepath"
"regexp"
"strings"
@@ -12,10 +11,6 @@ import (
)
var _ = Describe("odo generic", func() {
var testPHPGitURL = "https://github.com/appuio/example-php-sti-helloworld"
var testNodejsGitURL = "https://github.com/sclorg/nodejs-ex"
var testLongURLName = "long-url-name-long-url-name-long-url-name-long-url-name-long-url-name"
// TODO: A neater way to provide odo path. Currently we assume \
// odo and oc in $PATH already
var oc helper.OcRunner
@@ -129,77 +124,6 @@ var _ = Describe("odo generic", func() {
})
})
Context("creating component with an application and url", func() {
JustBeforeEach(func() {
helper.Chdir(commonVar.Context)
})
It("should create the component in default application", func() {
helper.Cmd("odo", "create", "--s2i", "php", "testcmp", "--app", "e2e-xyzk", "--project", commonVar.Project, "--git", testPHPGitURL).ShouldPass()
helper.Cmd("odo", "config", "set", "Ports", "8080/TCP", "-f").ShouldPass()
helper.Cmd("odo", "push").ShouldPass()
oc.VerifyCmpName("testcmp", commonVar.Project)
oc.VerifyAppNameOfComponent("testcmp", "e2e-xyzk", commonVar.Project)
helper.Cmd("odo", "app", "delete", "e2e-xyzk", "-f").ShouldPass()
})
})
Context("Overwriting build timeout for git component", func() {
JustBeforeEach(func() {
helper.Chdir(commonVar.Context)
})
It("should pass to build component if the given build timeout is more than the default(300s) value", func() {
helper.Cmd("odo", "create", "--s2i", "nodejs", "nodejs", "--project", commonVar.Project, "--git", testNodejsGitURL).ShouldPass()
helper.Cmd("odo", "preference", "set", "BuildTimeout", "600").ShouldPass()
buildTimeout := helper.GetPreferenceValue("BuildTimeout")
helper.MatchAllInOutput(buildTimeout, []string{"600"})
helper.Cmd("odo", "push").ShouldPass()
})
It("should fail to build component if the given build timeout is pretty less(2s)", func() {
helper.Cmd("odo", "create", "--s2i", "nodejs", "nodejs", "--project", commonVar.Project, "--git", testNodejsGitURL).ShouldPass()
helper.Cmd("odo", "preference", "set", "BuildTimeout", "2").ShouldPass()
buildTimeout := helper.GetPreferenceValue("BuildTimeout")
helper.MatchAllInOutput(buildTimeout, []string{"2"})
stdOut := helper.Cmd("odo", "push").ShouldFail().Err()
helper.MatchAllInOutput(stdOut, []string{"Failed to create component", "timeout waiting for build"})
})
})
Context("should list applications in other project", func() {
It("should be able to create a php component with application created", func() {
helper.Cmd("odo", "create", "--s2i", "php", "testcmp", "--app", "testing", "--project", commonVar.Project, "--ref", "master", "--git", testPHPGitURL, "--context", commonVar.Context).ShouldPass()
helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass()
currentProject := helper.CreateRandProject()
currentAppNames := helper.Cmd("odo", "app", "list", "--project", currentProject).ShouldPass().Out()
Expect(currentAppNames).To(ContainSubstring("There are no applications deployed in the project '" + currentProject + "'"))
appNames := helper.Cmd("odo", "app", "list", "--project", commonVar.Project).ShouldPass().Out()
Expect(appNames).To(ContainSubstring("testing"))
helper.DeleteProject(currentProject)
})
})
Context("when running odo push with flag --show-log", func() {
// works
It("should be able to push changes", func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.Cmd("odo", "create", "--s2i", "nodejs", "nodejs", "--project", commonVar.Project, "--context", commonVar.Context).ShouldPass()
// Push the changes with --show-log
getLogging := helper.Cmd("odo", "push", "--show-log", "--context", commonVar.Context).ShouldPass().Out()
Expect(getLogging).To(ContainSubstring("Creating Kubernetes resources for component nodejs"))
})
})
Context("deploying a component with a specific image name", func() {
It("should deploy the component", func() {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
helper.Cmd("odo", "create", "--s2i", "nodejs:latest", "testversioncmp", "--project", commonVar.Project, "--context", commonVar.Context).ShouldPass()
helper.Cmd("odo", "push", "--context", commonVar.Context).ShouldPass()
helper.Cmd("odo", "delete", "-f", "--context", commonVar.Context).ShouldPass()
})
})
Context("When deleting two project one after the other", func() {
It("should be able to delete sequentially", func() {
project1 := helper.CreateRandProject()
@@ -237,61 +161,4 @@ var _ = Describe("odo generic", func() {
})
})
Context("prevent the user from creating invalid URLs", func() {
JustBeforeEach(func() {
helper.Chdir(commonVar.Context)
})
It("should not allow creating a URL with long name", func() {
helper.Cmd("odo", "create", "--s2i", "nodejs", "--project", commonVar.Project).ShouldPass()
stdOut := helper.Cmd("odo", "url", "create", testLongURLName, "--port", "8080").ShouldFail().Err()
Expect(stdOut).To(ContainSubstring("must be shorter than 63 characters"))
})
})
Context("When using cpu or memory flag with odo create", func() {
cmpName := "nodejs"
JustBeforeEach(func() {
helper.Chdir(commonVar.Context)
})
It("should not allow using any memory or cpu flag", func() {
cases := []struct {
paramName string
paramValue string
}{
{
paramName: "cpu",
paramValue: "0.4",
},
{
paramName: "mincpu",
paramValue: "0.2",
},
{
paramName: "maxcpu",
paramValue: "0.4",
},
{
paramName: "memory",
paramValue: "200Mi",
},
{
paramName: "minmemory",
paramValue: "100Mi",
},
{
paramName: "maxmemory",
paramValue: "200Mi",
},
}
for _, testCase := range cases {
helper.CopyExample(filepath.Join("source", "nodejs"), commonVar.Context)
output := helper.Cmd("odo", "component", "create", "--s2i", "nodejs", cmpName, "--project", commonVar.Project, "--context", commonVar.Context, "--"+testCase.paramName, testCase.paramValue, "--git", "https://github.com/sclorg/nodejs-ex.git").ShouldFail().Err()
Expect(output).To(ContainSubstring("unknown flag: --" + testCase.paramName))
}
})
})
})