Skip to content

Commit

Permalink
Removes invalid endpoints from the devfile on triggering url create.
Browse files Browse the repository at this point in the history
It also modifies the error messages when no port is provided.

Signed-off-by: mik-dass <mrinald7@gmail.com>
  • Loading branch information
mik-dass committed Apr 21, 2021
1 parent 66935fc commit 9a95980
Show file tree
Hide file tree
Showing 9 changed files with 562 additions and 52 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ require (
k8s.io/cli-runtime v0.17.0
k8s.io/client-go v12.0.0+incompatible
k8s.io/klog v1.0.0
k8s.io/klog/v2 v2.0.0
k8s.io/kubectl v0.0.0
sigs.k8s.io/yaml v1.2.0
)
Expand Down
2 changes: 2 additions & 0 deletions pkg/config/url.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ func (lc *LocalConfig) GetPorts() ([]string, error) {
func (lc *LocalConfig) CompleteURL(url *localConfigProvider.LocalURL) error {
var err error

url.Kind = localConfigProvider.ROUTE

ports, err := lc.GetPorts()
if err != nil {
return err
Expand Down
7 changes: 7 additions & 0 deletions pkg/envinfo/envinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ const (
// EnvInfo holds all the env specific information relevant to a specific Component.
type EnvInfo struct {
devfileObj parser.DevfileObj
isRouteSupported bool
updateURL bool // this indicates that the URL create operation should be an update operation
componentSettings ComponentSettings `yaml:"ComponentSettings,omitempty"`
}

Expand Down Expand Up @@ -424,6 +426,11 @@ func (ei *EnvInfo) GetDevfileObj() parser.DevfileObj {
return ei.devfileObj
}

// SetIsRouteSupported sets the isRouteSupported value for the envinfo
func (ei *EnvInfo) SetIsRouteSupported(isRouteSupported bool) {
ei.isRouteSupported = isRouteSupported
}

// GetLink returns the EnvInfoLink, returns default if nil
func (ei *EnvInfo) GetLink() []EnvInfoLink {
if ei.componentSettings.Link == nil {
Expand Down
147 changes: 122 additions & 25 deletions pkg/envinfo/url.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ func (ei *EnvInfo) GetPorts() ([]string, error) {

// CompleteURL completes the given URL with default values
func (ei *EnvInfo) CompleteURL(url *localConfigProvider.LocalURL) error {
if url.Kind == "" {
if !ei.isRouteSupported {
url.Kind = localConfigProvider.INGRESS
} else {
url.Kind = localConfigProvider.ROUTE
}
}

if len(url.Path) > 0 && (strings.HasPrefix(url.Path, "/") || strings.HasPrefix(url.Path, "\\")) {
if len(url.Path) <= 1 {
url.Path = ""
Expand All @@ -59,16 +67,32 @@ func (ei *EnvInfo) CompleteURL(url *localConfigProvider.LocalURL) error {
return err
}
if url.Port == -1 {
var err error
url.Port, err = util.GetValidPortNumber(ei.GetName(), url.Port, ports)
if err != nil {
return err
if len(ports) > 1 {
return fmt.Errorf("port for the component %s is required as it exposes %d ports: %s", ei.GetName(), len(ports), strings.Trim(strings.Replace(fmt.Sprint(ports), " ", ",", -1), "[]"))
} else if len(ports) <= 0 {
return fmt.Errorf("no port is exposed by the component %s, please specify a port", ei.GetName())
} else {
url.Port, err = strconv.Atoi(strings.Split(ports[0], "/")[0])
if err != nil {
return err
}
}
}

// get the name for the URL if not provided
if len(url.Name) == 0 {
url.Name = util.GetURLName(ei.GetName(), url.Port)
foundURL, err := findInvalidEndpoint(ei, url.Port)
if err != nil {
return err
}

if foundURL.Name != "" {
// found an URL that can be overridden or more info can be added to it
url.Name = foundURL.Name
ei.updateURL = true
} else {
url.Name = util.GetURLName(ei.GetName(), url.Port)
}
}

containerComponents, err := ei.devfileObj.Data.GetDevfileContainerComponents(common.DevfileOptions{})
Expand Down Expand Up @@ -131,7 +155,7 @@ func (ei *EnvInfo) ValidateURL(url localConfigProvider.LocalURL) error {
}
}
for _, endpoint := range component.Container.Endpoints {
if endpoint.Name == url.Name {
if endpoint.Name == url.Name && !ei.updateURL {
return fmt.Errorf("url %v already exist in devfile endpoint entry under container %v", url.Name, component.Name)
}
containerPortMap[endpoint.TargetPort] = component.Name
Expand Down Expand Up @@ -184,13 +208,15 @@ func (ei *EnvInfo) ValidateURL(url localConfigProvider.LocalURL) error {
}
}

urls, err := ei.ListURLs()
if err != nil {
return err
}
for _, localURL := range urls {
if url.Name == localURL.Name {
errorList = append(errorList, fmt.Sprintf("URL %s already exists", url.Name))
if !ei.updateURL {
urls, err := ei.ListURLs()
if err != nil {
return err
}
for _, localURL := range urls {
if url.Name == localURL.Name {
errorList = append(errorList, fmt.Sprintf("URL %s already exists", url.Name))
}
}
}

Expand All @@ -216,20 +242,29 @@ func (ei *EnvInfo) GetURL(name string) (*localConfigProvider.LocalURL, error) {

// CreateURL write the given url to the env.yaml and devfile
func (esi *EnvSpecificInfo) CreateURL(url localConfigProvider.LocalURL) error {
newEndpointEntry := devfilev1.Endpoint{
Name: url.Name,
Path: url.Path,
Secure: url.Secure,
Exposure: devfilev1.PublicEndpointExposure,
TargetPort: url.Port,
Protocol: devfilev1.EndpointProtocol(strings.ToLower(url.Protocol)),
}

err := addEndpointInDevfile(esi.devfileObj, newEndpointEntry, url.Container)
if err != nil {
return errors.Wrapf(err, "failed to write endpoints information into devfile")
if !esi.updateURL {
newEndpointEntry := devfilev1.Endpoint{
Name: url.Name,
Path: url.Path,
Secure: url.Secure,
Exposure: devfilev1.PublicEndpointExposure,
TargetPort: url.Port,
Protocol: devfilev1.EndpointProtocol(strings.ToLower(url.Protocol)),
}

err := addEndpointInDevfile(esi.devfileObj, newEndpointEntry, url.Container)
if err != nil {
return errors.Wrapf(err, "failed to write endpoints information into devfile")
}
} else {
err := updateEndpointInDevfile(esi.devfileObj, url)
if err != nil {
return err
}
}
err = esi.SetConfiguration("url", localConfigProvider.LocalURL{Name: url.Name, Host: url.Host, TLSSecret: url.TLSSecret, Kind: url.Kind})

err := esi.SetConfiguration("url", localConfigProvider.LocalURL{Name: url.Name, Host: url.Host, TLSSecret: url.TLSSecret, Kind: url.Kind})
if err != nil {
return errors.Wrapf(err, "failed to persist the component settings to env file")
}
Expand Down Expand Up @@ -358,3 +393,65 @@ func removeEndpointInDevfile(devObj parser.DevfileObj, urlName string) error {
}
return devObj.WriteYamlDevfile()
}

// updateEndpointInDevfile updates the endpoint of the given URL in the devfile
func updateEndpointInDevfile(devObj parser.DevfileObj, url localConfigProvider.LocalURL) error {
components, err := devObj.Data.GetComponents(common.DevfileOptions{})
if err != nil {
return err
}
for _, component := range components {
if component.Container != nil && component.Name == url.Container {
for j := range component.ComponentUnion.Container.Endpoints {
endpoint := component.ComponentUnion.Container.Endpoints[j]

if endpoint.Name == url.Name {
// fill the default values
if endpoint.Exposure == "" {
endpoint.Exposure = devfilev1.PublicEndpointExposure
}
if endpoint.Path == "" {
endpoint.Path = "/"
}
if endpoint.Protocol == "" {
endpoint.Protocol = devfilev1.HTTPEndpointProtocol
}

// prevent write unless required
if endpoint.Exposure != devfilev1.PublicEndpointExposure || url.Secure != endpoint.Secure ||
url.Path != endpoint.Path || url.Protocol != string(endpoint.Protocol) {
endpoint = devfilev1.Endpoint{
Name: url.Name,
Path: url.Path,
Secure: url.Secure,
Exposure: devfilev1.PublicEndpointExposure,
TargetPort: url.Port,
Protocol: devfilev1.EndpointProtocol(strings.ToLower(url.Protocol)),
}
component.ComponentUnion.Container.Endpoints[j] = endpoint
devObj.Data.UpdateComponent(component)
return devObj.WriteYamlDevfile()
}
return nil
}
}
}
}
return fmt.Errorf("url %s not found for updating", url.Name)
}

// findInvalidEndpoint finds the URLs which are invalid for the current cluster e.g
// route urls on a vanilla k8s based cluster
// urls with no host information on a vanilla k8s based cluster
func findInvalidEndpoint(ei *EnvInfo, port int) (localConfigProvider.LocalURL, error) {
urls, err := ei.ListURLs()
if err != nil {
return localConfigProvider.LocalURL{}, err
}
for _, url := range urls {
if url.Kind == localConfigProvider.ROUTE && url.Port == port && !ei.isRouteSupported {
return url, nil
}
}
return localConfigProvider.LocalURL{}, nil
}
Loading

0 comments on commit 9a95980

Please sign in to comment.