github.com/ouraigua/jenkins-library@v0.0.0-20231028010029-fbeaf2f3aa9b/pkg/cnbutils/project/descriptor.go (about)

     1  // Package project handles project.toml parsing
     2  package project
     3  
     4  import (
     5  	"github.com/pkg/errors"
     6  
     7  	"github.com/BurntSushi/toml"
     8  	"github.com/SAP/jenkins-library/pkg/cnbutils"
     9  	"github.com/SAP/jenkins-library/pkg/cnbutils/project/types"
    10  	v01 "github.com/SAP/jenkins-library/pkg/cnbutils/project/v01"
    11  	v02 "github.com/SAP/jenkins-library/pkg/cnbutils/project/v02"
    12  	"github.com/SAP/jenkins-library/pkg/cnbutils/registry"
    13  	piperhttp "github.com/SAP/jenkins-library/pkg/http"
    14  	"github.com/SAP/jenkins-library/pkg/log"
    15  	ignore "github.com/sabhiram/go-gitignore"
    16  )
    17  
    18  type project struct {
    19  	Version string `toml:"schema-version"`
    20  }
    21  
    22  type versionDescriptor struct {
    23  	Project project `toml:"_"`
    24  }
    25  
    26  var parsers = map[string]func(string) (types.Descriptor, error){
    27  	"0.1": v01.NewDescriptor,
    28  	"0.2": v02.NewDescriptor,
    29  }
    30  
    31  type Descriptor struct {
    32  	Exclude        *ignore.GitIgnore
    33  	Include        *ignore.GitIgnore
    34  	EnvVars        map[string]interface{}
    35  	Buildpacks     []string
    36  	PreBuildpacks  []string
    37  	PostBuildpacks []string
    38  	ProjectID      string
    39  }
    40  
    41  func ParseDescriptor(descriptorPath string, utils cnbutils.BuildUtils, httpClient piperhttp.Sender) (*Descriptor, error) {
    42  	descriptor := &Descriptor{}
    43  
    44  	descriptorContent, err := utils.FileRead(descriptorPath)
    45  	if err != nil {
    46  		return nil, err
    47  	}
    48  
    49  	var versionDescriptor versionDescriptor
    50  	_, err = toml.Decode(string(descriptorContent), &versionDescriptor)
    51  	if err != nil {
    52  		return &Descriptor{}, errors.Wrapf(err, "parsing schema version")
    53  	}
    54  
    55  	version := versionDescriptor.Project.Version
    56  	if version == "" {
    57  		version = "0.1"
    58  	}
    59  
    60  	rawDescriptor, err := parsers[version](string(descriptorContent))
    61  	if err != nil {
    62  		return &Descriptor{}, err
    63  	}
    64  
    65  	if len(rawDescriptor.Build.Buildpacks) > 0 {
    66  		descriptor.Buildpacks, err = searchBuildpacks(rawDescriptor.Build.Buildpacks, httpClient)
    67  		if err != nil {
    68  			return nil, err
    69  		}
    70  	}
    71  
    72  	if len(rawDescriptor.Build.Pre.Buildpacks) > 0 {
    73  		descriptor.PreBuildpacks, err = searchBuildpacks(rawDescriptor.Build.Pre.Buildpacks, httpClient)
    74  		if err != nil {
    75  			return nil, err
    76  		}
    77  	}
    78  
    79  	if len(rawDescriptor.Build.Post.Buildpacks) > 0 {
    80  		descriptor.PostBuildpacks, err = searchBuildpacks(rawDescriptor.Build.Post.Buildpacks, httpClient)
    81  		if err != nil {
    82  			return nil, err
    83  		}
    84  	}
    85  
    86  	if len(rawDescriptor.Build.Env) > 0 {
    87  		descriptor.EnvVars = envToMap(rawDescriptor.Build.Env)
    88  	}
    89  
    90  	if len(rawDescriptor.Build.Exclude) > 0 && len(rawDescriptor.Build.Include) > 0 {
    91  		return nil, errors.New("project descriptor options 'exclude' and 'include' are mutually exclusive")
    92  	}
    93  
    94  	if len(rawDescriptor.Build.Exclude) > 0 {
    95  		descriptor.Exclude = ignore.CompileIgnoreLines(rawDescriptor.Build.Exclude...)
    96  	}
    97  
    98  	if len(rawDescriptor.Build.Include) > 0 {
    99  		descriptor.Include = ignore.CompileIgnoreLines(rawDescriptor.Build.Include...)
   100  	}
   101  
   102  	if len(rawDescriptor.Project.ID) > 0 {
   103  		descriptor.ProjectID = rawDescriptor.Project.ID
   104  	}
   105  
   106  	return descriptor, nil
   107  }
   108  
   109  func envToMap(env []types.EnvVar) map[string]interface{} {
   110  	envMap := map[string]interface{}{}
   111  
   112  	for _, e := range env {
   113  		if len(e.Name) == 0 {
   114  			continue
   115  		}
   116  
   117  		envMap[e.Name] = e.Value
   118  	}
   119  
   120  	return envMap
   121  }
   122  
   123  func searchBuildpacks(buildpacks []types.Buildpack, httpClient piperhttp.Sender) ([]string, error) {
   124  	var bpackImg []string
   125  
   126  	for _, bpack := range buildpacks {
   127  		if bpack.Script != (types.Script{}) {
   128  			return nil, errors.New("inline buildpacks are not supported")
   129  		}
   130  
   131  		if bpack.URI != "" {
   132  			log.Entry().Debugf("Adding buildpack using URI: %s", bpack.URI)
   133  			bpackImg = append(bpackImg, bpack.URI)
   134  		} else if bpack.ID != "" {
   135  			imgURL, err := registry.SearchBuildpack(bpack.ID, bpack.Version, httpClient, "")
   136  			if err != nil {
   137  				return nil, err
   138  			}
   139  
   140  			bpackImg = append(bpackImg, imgURL)
   141  		} else {
   142  			return nil, errors.New("invalid buildpack entry in project.toml, either URI or ID should be specified")
   143  		}
   144  
   145  	}
   146  
   147  	return bpackImg, nil
   148  }