...

Source file src/github.com/redhat-developer/odo/pkg/alizer/alizer.go

Documentation: github.com/redhat-developer/odo/pkg/alizer

     1  package alizer
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"os"
     7  	"path/filepath"
     8  
     9  	"github.com/devfile/alizer/pkg/apis/model"
    10  	"github.com/devfile/alizer/pkg/apis/recognizer"
    11  	"k8s.io/klog"
    12  
    13  	"github.com/redhat-developer/odo/pkg/api"
    14  	"github.com/redhat-developer/odo/pkg/registry"
    15  	"github.com/redhat-developer/odo/pkg/util"
    16  )
    17  
    18  type Alizer struct {
    19  	registryClient registry.Client
    20  }
    21  
    22  var _ Client = (*Alizer)(nil)
    23  
    24  func NewAlizerClient(registryClient registry.Client) *Alizer {
    25  	return &Alizer{
    26  		registryClient: registryClient,
    27  	}
    28  }
    29  
    30  // DetectFramework uses the alizer library in order to detect the devfile
    31  // to use depending on the files in the path
    32  func (o *Alizer) DetectFramework(ctx context.Context, path string) (DetectedFramework, error) {
    33  	types := []model.DevfileType{}
    34  	components, err := o.registryClient.ListDevfileStacks(ctx, "", "", "", false, false)
    35  	if err != nil {
    36  		return DetectedFramework{}, err
    37  	}
    38  	for _, component := range components.Items {
    39  		types = append(types, model.DevfileType{
    40  			Name:        component.Name,
    41  			Language:    component.Language,
    42  			ProjectType: component.ProjectType,
    43  			Tags:        component.Tags,
    44  		})
    45  	}
    46  	typ, err := recognizer.SelectDevFileFromTypes(path, types)
    47  	if err != nil {
    48  		return DetectedFramework{}, err
    49  	}
    50  	// Get the default stack version that will be downloaded
    51  	var defaultVersion string
    52  	for _, version := range components.Items[typ].Versions {
    53  		if version.IsDefault {
    54  			defaultVersion = version.Version
    55  		}
    56  	}
    57  	return DetectedFramework{
    58  		Type:           types[typ],
    59  		DefaultVersion: defaultVersion,
    60  		Registry:       components.Items[typ].Registry,
    61  		Architectures:  components.Items[typ].Architectures,
    62  	}, nil
    63  }
    64  
    65  // DetectName retrieves the name of the project (if available).
    66  // If source code is detected:
    67  // 1. Detect the name (pom.xml for java, package.json for nodejs, etc.)
    68  // 2. If unable to detect the name, use the directory name
    69  //
    70  // If no source is detected:
    71  // 1. Use the directory name
    72  //
    73  // Last step. Sanitize the name so it's valid for a component name
    74  //
    75  // Use:
    76  // import "github.com/redhat-developer/alizer/pkg/apis/recognizer"
    77  // components, err := recognizer.DetectComponents("./")
    78  //
    79  // In order to detect the name, the name will first try to find out the name based on the program (pom.xml, etc.) but then if not, it will use the dir name.
    80  func (o *Alizer) DetectName(path string) (string, error) {
    81  	if path == "" {
    82  		return "", fmt.Errorf("path is empty")
    83  	}
    84  
    85  	// Check if the path exists using os.Stat
    86  	dir, err := os.Stat(path)
    87  	if err != nil {
    88  		return "", err
    89  	}
    90  
    91  	// Check to see if the path is a directory, and fail if it is not
    92  	if !dir.IsDir() {
    93  		return "", fmt.Errorf("alizer DetectName %q path is not a directory", path)
    94  	}
    95  
    96  	// Step 1.
    97  	// Get the name of the directory from the devfile absolute path
    98  	// Use that path with Alizer to get the name of the project,
    99  	// if unable to find the name, we will use the directory name
   100  	components, err := recognizer.DetectComponents(path)
   101  	if err != nil {
   102  		return "", err
   103  	}
   104  	klog.V(4).Infof("Found components: %v", components)
   105  
   106  	// Take the first name that is found
   107  	var detectedName string
   108  	if len(components) > 0 {
   109  		detectedName = components[0].Name
   110  	}
   111  
   112  	// Step 2. If unable to detect the name, we will use the directory name.
   113  	// Alizer will not correctly default to the directory name when unable to detect it via pom.xml, package.json, etc.
   114  	// So we must do it ourselves
   115  	// The directory name SHOULD be the path (we use a previous check to see if it's "itsdir"
   116  	if detectedName == "" {
   117  		detectedName = filepath.Base(path)
   118  	}
   119  
   120  	// Step 3.  Sanitize the name
   121  	// Make sure that detectedName conforms with Kubernetes naming rules
   122  	// If not, we will use the directory name
   123  	name := util.GetDNS1123Name(detectedName)
   124  	klog.V(4).Infof("Path: %s, Detected name: %s, Sanitized name: %s", path, detectedName, name)
   125  	if name == "" {
   126  		return "", fmt.Errorf("unable to sanitize name to DNS1123 format: %q", name)
   127  	}
   128  
   129  	return name, nil
   130  }
   131  
   132  func (o *Alizer) DetectPorts(path string) ([]int, error) {
   133  	//TODO(rm3l): Find a better way not to call recognizer.DetectComponents multiple times (in DetectFramework, DetectName and DetectPorts)
   134  	components, err := recognizer.DetectComponents(path)
   135  	if err != nil {
   136  		return nil, err
   137  	}
   138  
   139  	if len(components) == 0 {
   140  		klog.V(4).Infof("no components found at path %q", path)
   141  		return nil, nil
   142  	}
   143  
   144  	return components[0].Ports, nil
   145  }
   146  
   147  func NewDetectionResult(typ model.DevfileType, registry api.Registry, appPorts []int, devfileVersion, name string) *api.DetectionResult {
   148  	return &api.DetectionResult{
   149  		Devfile:          typ.Name,
   150  		DevfileRegistry:  registry.Name,
   151  		ApplicationPorts: appPorts,
   152  		DevfileVersion:   devfileVersion,
   153  		Name:             name,
   154  	}
   155  }
   156  

View as plain text