Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
rm3l committed Aug 26, 2022
1 parent 644d94c commit 16a2835
Show file tree
Hide file tree
Showing 19 changed files with 1,529 additions and 989 deletions.
8 changes: 7 additions & 1 deletion pkg/binding/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"

"github.com/redhat-developer/odo/pkg/component"
sboApi "github.com/redhat-developer/service-binding-operator/apis/binding/v1alpha1"

"github.com/redhat-developer/odo/pkg/binding/asker"
Expand Down Expand Up @@ -112,7 +113,12 @@ func (o *BindingClient) AddBindingToDevfile(
return obj, err
}

deploymentName := fmt.Sprintf("%s-app", obj.GetMetadataName())
componentName, err := component.GatherName(obj)
if err != nil {
return obj, err
}

deploymentName := fmt.Sprintf("%s-app", componentName)
deploymentGVK, err := o.kubernetesClient.GetDeploymentAPIVersion()
if err != nil {
return obj, err
Expand Down
45 changes: 21 additions & 24 deletions pkg/component/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,17 @@ import (
"github.com/devfile/library/pkg/devfile/parser"
"github.com/devfile/library/pkg/devfile/parser/data"
dfutil "github.com/devfile/library/pkg/util"
"k8s.io/klog"

"github.com/redhat-developer/odo/pkg/alizer"
"github.com/redhat-developer/odo/pkg/api"
"github.com/redhat-developer/odo/pkg/kclient"
"github.com/redhat-developer/odo/pkg/labels"
odolabels "github.com/redhat-developer/odo/pkg/labels"
"github.com/redhat-developer/odo/pkg/util"

corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/klog"
)

const (
Expand All @@ -42,32 +44,27 @@ func GetComponentTypeFromDevfileMetadata(metadata devfile.DevfileMetadata) strin
return componentType
}

// GatherName parses the Devfile and retrieves an appropriate name in two ways.
// 1. If metadata.name exists, we use it
// 2. If metadata.name does NOT exist, we use the folder name where the devfile.yaml is located
func GatherName(devObj parser.DevfileObj, devfilePath string) (string, error) {

metadata := devObj.Data.GetMetadata()

klog.V(4).Infof("metadata.Name: %s", metadata.Name)

// 1. Use metadata.name if it exists
if metadata.Name != "" {

// Remove any suffix's that end with `-`. This is because many Devfile's use the original v1 Devfile pattern of
// having names such as "foo-bar-" in order to prepend container names such as "foo-bar-container1"
return strings.TrimSuffix(metadata.Name, "-"), nil
// GatherName returns the name of the component.
//
// If a name is set in the Devfile metadata (which is optional) and is not blank, it returns that.
//
// Otherwise, it uses Alizer to detect the name of the component, from the project build tools (pom.xml, package.json, ...),
// or from the component directory name.
func GatherName(devfileObj parser.DevfileObj) (string, error) {
devfilePath := devfileObj.Ctx.GetAbsPath()
name := devfileObj.GetMetadataName()
if name == "" || strings.TrimSpace(name) == "" {
// Use Alizer if Devfile has no (optional) metadata.name field.
// We need to pass in the Devfile base directory (not the path to the devfile.yaml).
// Name returned by alizer.DetectName is expected to be already sanitized.
return alizer.DetectName(filepath.Dir(devfilePath))
}

// 2. Use the folder name as a last resort if nothing else exists
sourcePath, err := dfutil.GetAbsPath(devfilePath)
if err != nil {
return "", fmt.Errorf("unable to get source path: %w", err)
}
klog.V(4).Infof("Source path: %s", sourcePath)
klog.V(4).Infof("devfile dir: %s", filepath.Dir(sourcePath))
//sanitize the name
s := util.GetDNS1123Name(name)
klog.V(3).Infof("For Devfile at path %q, name of component is %q, and sanitized name is %q", devfilePath, name, s)

return filepath.Base(filepath.Dir(sourcePath)), nil
return s, nil
}

// Exists checks whether a component with the given name exists in the current application or not
Expand Down
129 changes: 127 additions & 2 deletions pkg/component/component_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,28 @@ package component

import (
"errors"
"os"
"path"
"path/filepath"
"reflect"
"testing"

devfilepkg "github.com/devfile/api/v2/pkg/devfile"
"github.com/devfile/library/pkg/devfile"
"github.com/devfile/library/pkg/devfile/parser"
devfileCtx "github.com/devfile/library/pkg/devfile/parser/context"
"github.com/devfile/library/pkg/devfile/parser/data"
"github.com/devfile/library/pkg/testingutil/filesystem"
dfutil "github.com/devfile/library/pkg/util"
"github.com/golang/mock/gomock"
"github.com/kylelemons/godebug/pretty"

"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"

"github.com/redhat-developer/odo/pkg/kclient"
"github.com/redhat-developer/odo/pkg/labels"

"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"github.com/redhat-developer/odo/pkg/testingutil"
"github.com/redhat-developer/odo/pkg/util"

"github.com/redhat-developer/odo/pkg/api"
)
Expand Down Expand Up @@ -345,3 +356,117 @@ func TestGetRunningModes(t *testing.T) {
})
}
}

func TestGatherName(t *testing.T) {
type devfileProvider func() (parser.DevfileObj, string, error)
fakeDevfileWithNameProvider := func(name string) devfileProvider {
return func() (parser.DevfileObj, string, error) {
dData, err := data.NewDevfileData(string(data.APISchemaVersion220))
if err != nil {
return parser.DevfileObj{}, "", err
}
dData.SetMetadata(devfilepkg.DevfileMetadata{Name: name})
return parser.DevfileObj{
Ctx: devfileCtx.FakeContext(filesystem.NewFakeFs(), parser.OutputDevfileYamlPath),
Data: dData,
}, "", nil
}
}

fs := filesystem.DefaultFs{}
//realDevfileWithNameProvider creates a real temporary directory and writes a devfile with the given name to it.
//It is the responsibility of the caller to remove the directory.
realDevfileWithNameProvider := func(name string) devfileProvider {
return func() (parser.DevfileObj, string, error) {
dir, err := fs.TempDir("", "Component_GatherName_")
if err != nil {
return parser.DevfileObj{}, dir, err
}

originalDevfile := testingutil.GetTestDevfileObjFromFile("devfile.yaml")
originalDevfilePath := originalDevfile.Ctx.GetAbsPath()

stat, err := os.Stat(originalDevfilePath)
if err != nil {
return parser.DevfileObj{}, dir, err
}
dPath := path.Join(dir, "devfile.yaml")
err = dfutil.CopyFile(originalDevfilePath, dPath, stat)
if err != nil {
return parser.DevfileObj{}, dir, err
}

var d parser.DevfileObj
d, _, err = devfile.ParseDevfileAndValidate(parser.ParserArgs{Path: dPath})
if err != nil {
return parser.DevfileObj{}, dir, err
}

err = d.SetMetadataName(name)

return d, dir, err
}
}

wantDevfileDirectoryName := func(d parser.DevfileObj) string {
return util.GetDNS1123Name(filepath.Base(filepath.Dir(d.Ctx.GetAbsPath())))
}

for _, tt := range []struct {
name string
devfileProviderFunc devfileProvider
wantErr bool
want func(parser.DevfileObj) string
}{
{
name: "compliant name",
devfileProviderFunc: fakeDevfileWithNameProvider("my-component-name"),
want: func(parser.DevfileObj) string { return "my-component-name" },
},
{
name: "un-sanitized name",
devfileProviderFunc: fakeDevfileWithNameProvider("name with spaces"),
want: func(parser.DevfileObj) string { return "name-with-spaces" },
},
{
name: "all numeric name",
devfileProviderFunc: fakeDevfileWithNameProvider("123456789"),
// "x" prefix added by util.GetDNS1123Name
want: func(parser.DevfileObj) string { return "x123456789" },
},
{
name: "no name",
devfileProviderFunc: realDevfileWithNameProvider(""),
want: wantDevfileDirectoryName,
},
{
name: "blank name",
devfileProviderFunc: realDevfileWithNameProvider(" "),
want: wantDevfileDirectoryName,
},
} {
t.Run(tt.name, func(t *testing.T) {
d, dir, dErr := tt.devfileProviderFunc()
if dir != "" {
defer func(fs filesystem.DefaultFs, path string) {
if err := fs.RemoveAll(path); err != nil {
t.Logf("error while attempting to remove temporary directory %q: %v", path, err)
}
}(fs, dir)
}
if dErr != nil {
t.Errorf("error when building test Devfile object: %v", dErr)
return
}

got, err := GatherName(d)
if (err != nil) != tt.wantErr {
t.Errorf("error = %v, wantErr %v", err, tt.wantErr)
}
want := tt.want(d)
if !reflect.DeepEqual(got, want) {
t.Errorf("GatherName() = %q, want = %q", got, want)
}
})
}
}
14 changes: 12 additions & 2 deletions pkg/component/delete/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,12 @@ func (do DeleteComponentClient) ListResourcesToDeleteFromDevfile(devfileObj pars
if mode == odolabels.ComponentDevMode || mode == odolabels.ComponentAnyMode {
// Inner Loop
// Fetch the deployment of the devfile component
componentName := devfileObj.GetMetadataName()
var componentName string
componentName, err = component.GatherName(devfileObj)
if err != nil {
return isInnerLoopDeployed, resources, err
}

var deploymentName string
deploymentName, err = util.NamespaceKubernetesObject(componentName, appName)
if err != nil {
Expand Down Expand Up @@ -155,7 +160,12 @@ func (do *DeleteComponentClient) ExecutePreStopEvents(devfileObj parser.DevfileO
if !libdevfile.HasPreStopEvents(devfileObj) {
return nil
}
componentName := devfileObj.GetMetadataName()

componentName, err := component.GatherName(devfileObj)
if err != nil {
return err
}

klog.V(4).Infof("Gathering information for component: %q", componentName)

klog.V(3).Infof("Checking component status for %q", componentName)
Expand Down
22 changes: 17 additions & 5 deletions pkg/dev/dev.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ import (
"github.com/devfile/library/pkg/devfile/parser"
"k8s.io/klog/v2"

"github.com/redhat-developer/odo/pkg/component"
"github.com/redhat-developer/odo/pkg/devfile/adapters"
"github.com/redhat-developer/odo/pkg/devfile/adapters/kubernetes/component"
k8sComponent "github.com/redhat-developer/odo/pkg/devfile/adapters/kubernetes/component"
"github.com/redhat-developer/odo/pkg/watch"
)

Expand Down Expand Up @@ -58,10 +59,16 @@ func (o *DevClient) Start(
fs filesystem.Filesystem,
) (watch.ComponentStatus, error) {
klog.V(4).Infoln("Creating new adapter")
adapter := component.NewKubernetesAdapter(

componentName, err := component.GatherName(devfileObj)
if err != nil {
return watch.ComponentStatus{}, err
}

adapter := k8sComponent.NewKubernetesAdapter(
o.kubernetesClient, o.prefClient, o.portForwardClient, o.bindingClient,
component.AdapterContext{
ComponentName: devfileObj.GetMetadataName(),
k8sComponent.AdapterContext{
ComponentName: componentName,
Context: path,
AppName: "app",
Devfile: devfileObj,
Expand Down Expand Up @@ -118,10 +125,15 @@ func (o *DevClient) Watch(
return err
}

componentName, err := component.GatherName(devfileObj)
if err != nil {
return err
}

watchParameters := watch.WatchParameters{
DevfilePath: devfilePath,
Path: path,
ComponentName: devfileObj.GetMetadataName(),
ComponentName: componentName,
ApplicationName: "app",
DevfileWatchHandler: h.RegenerateAdapterAndPush,
EnvSpecificInfo: envSpecificInfo,
Expand Down
7 changes: 6 additions & 1 deletion pkg/devfile/adapters/kubernetes/component/commandhandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,14 @@ func ApplyKubernetes(mode, appName string, devfile parser.DevfileObj, kubernetes
return err
}

componentName, err := component.GatherName(devfile)
if err != nil {
return err
}

// Get the most common labels that's applicable to all resources being deployed.
// Set the mode. Regardless of what Kubernetes resource we are deploying.
labels := odolabels.GetLabels(devfile.Data.GetMetadata().Name, appName, mode, false)
labels := odolabels.GetLabels(componentName, appName, mode, false)

klog.V(4).Infof("Injecting labels: %+v into k8s artifact", labels)

Expand Down
6 changes: 5 additions & 1 deletion pkg/odo/cli/add/binding/binding.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (

"github.com/redhat-developer/odo/pkg/binding/asker"
"github.com/redhat-developer/odo/pkg/binding/backend"
"github.com/redhat-developer/odo/pkg/component"
"github.com/redhat-developer/odo/pkg/log"
"github.com/redhat-developer/odo/pkg/odo/cmdline"
"github.com/redhat-developer/odo/pkg/odo/genericclioptions"
Expand Down Expand Up @@ -123,7 +124,10 @@ func (o *AddBindingOptions) Run(_ context.Context) error {
}
componentName = workloadName
} else {
componentName = o.EnvSpecificInfo.GetDevfileObj().GetMetadataName()
componentName, err = component.GatherName(o.EnvSpecificInfo.GetDevfileObj())
if err != nil {
return err
}
}

bindingName, err := o.clientset.BindingClient.AskBindingName(serviceName, componentName, o.flags)
Expand Down
8 changes: 7 additions & 1 deletion pkg/odo/cli/delete/component/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
ktemplates "k8s.io/kubectl/pkg/util/templates"

"github.com/redhat-developer/odo/pkg/component"
"github.com/redhat-developer/odo/pkg/labels"
"github.com/redhat-developer/odo/pkg/log"
"github.com/redhat-developer/odo/pkg/odo/cli/ui"
Expand Down Expand Up @@ -122,7 +123,12 @@ func (o *ComponentOptions) deleteNamedComponent() error {
// deleteDevfileComponent deletes all the components defined by the devfile in the current directory
func (o *ComponentOptions) deleteDevfileComponent() error {
devfileObj := o.EnvSpecificInfo.GetDevfileObj()
componentName := devfileObj.GetMetadataName()

componentName, err := component.GatherName(devfileObj)
if err != nil {
return err
}

namespace := o.GetProject()
appName := "app"

Expand Down
9 changes: 7 additions & 2 deletions pkg/odo/cli/deploy/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,12 @@ func (o *DeployOptions) Validate() error {
// Run contains the logic for the odo command
func (o *DeployOptions) Run(ctx context.Context) error {
devfileObj := o.EnvSpecificInfo.GetDevfileObj()
devfileName := devfileObj.GetMetadataName()

devfileName, err := component.GatherName(devfileObj)
if err != nil {
return err
}

path := filepath.Dir(o.EnvSpecificInfo.GetDevfilePath())
appName := o.GetApplication()
namespace := o.GetProject()
Expand All @@ -129,7 +134,7 @@ func (o *DeployOptions) Run(ctx context.Context) error {
"odo version: "+version.VERSION)

// Run actual deploy command to be used
err := o.clientset.DeployClient.Deploy(o.clientset.FS, devfileObj, path, appName)
err = o.clientset.DeployClient.Deploy(o.clientset.FS, devfileObj, path, appName)

if err == nil {
log.Info("\nYour Devfile has been successfully deployed")
Expand Down
Loading

0 comments on commit 16a2835

Please sign in to comment.