github.com/ouraigua/jenkins-library@v0.0.0-20231028010029-fbeaf2f3aa9b/pkg/abap/aakaas/versionables.go (about) 1 package aakaas 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net/url" 7 "strconv" 8 "strings" 9 10 abapbuild "github.com/SAP/jenkins-library/pkg/abap/build" 11 "github.com/SAP/jenkins-library/pkg/log" 12 "github.com/pkg/errors" 13 ) 14 15 const wildCard string = "NEXT" 16 const statusFilterCV string = "DeliveryStatus eq 'R'" 17 const statusFilterPV string = "DeliveryStatus eq 'T' or DeliveryStatus eq 'P'" 18 19 type versionable struct { 20 Name string 21 Version string 22 TechRelease string 23 TechSpLevel string 24 TechPatchLevel string 25 26 connector abapbuild.Connector 27 queryUrl string 28 } 29 30 type versionables struct { 31 Wrapper struct { 32 Vs []versionable `json:"results"` 33 } `json:"d"` 34 } 35 36 func (v *versionable) constructVersionable(name string, dottedVersionString string, connector abapbuild.Connector, queryURL string) error { 37 if name == "" { 38 return errors.New("No Component/Product Name provided") 39 } 40 subStrings := strings.Split(dottedVersionString, ".") 41 if len(subStrings) != 3 { 42 return errors.New("Provide a dotted-version-string with 2 '.' [Release.SP.Patch]") 43 } 44 v.Name = name 45 v.TechRelease = subStrings[0] 46 v.TechSpLevel = fmt.Sprintf("%04s", subStrings[1]) 47 v.TechPatchLevel = fmt.Sprintf("%04s", subStrings[2]) 48 v.connector = connector 49 v.queryUrl = queryURL 50 v.Version = dottedVersionString 51 return nil 52 } 53 54 func (v *versionable) resolveNext(statusFilter string) error { 55 56 switch strings.Count(v.Version, wildCard) { 57 case 0: 58 return nil 59 case 1: 60 log.Entry().Info("Wildcard detected in dotted-version-string. Looking up highest existing package in AAKaaS...") 61 var err error 62 switch wildCard { 63 case v.TechRelease: 64 err = v.resolveRelease(statusFilter) 65 case v.TechSpLevel: 66 err = v.resolveSpLevel(statusFilter) 67 case v.TechPatchLevel: 68 err = v.resolvePatchLevel(statusFilter) 69 } 70 if err != nil { 71 return err 72 } 73 if v.Version, err = v.getDottedVersionString(); err != nil { 74 return err 75 } 76 default: 77 return errors.New("The dotted-version-string must contain only one wildcard " + wildCard) 78 } 79 80 return nil 81 } 82 83 func (v *versionable) resolveRelease(statusFilter string) error { 84 filter := "Name eq '" + v.Name + "' and TechSpLevel eq '0000' and TechPatchLevel eq '0000' and ( " + statusFilter + " )" 85 orderBy := "TechRelease desc" 86 87 if queryResuult, err := v.queryVersion(filter, orderBy); err != nil { 88 return err 89 } else { 90 if newRelease, err := strconv.Atoi(queryResuult.TechRelease); err != nil { 91 return err 92 } else { 93 v.TechRelease = strconv.Itoa(newRelease + 1) 94 return nil 95 } 96 } 97 } 98 99 func (v *versionable) resolveSpLevel(statusFilter string) error { 100 filter := "Name eq '" + v.Name + "' and TechRelease eq '" + v.TechRelease + "' and TechPatchLevel eq '0000' and ( " + statusFilter + " )" 101 orderBy := "TechSpLevel desc" 102 103 if queryResuult, err := v.queryVersion(filter, orderBy); err != nil { 104 return err 105 } else { 106 if newSpLevel, err := strconv.Atoi(queryResuult.TechSpLevel); err != nil { 107 return err 108 } else { 109 v.TechSpLevel = fmt.Sprintf("%04d", newSpLevel+1) 110 return nil 111 } 112 } 113 } 114 115 func (v *versionable) resolvePatchLevel(statusFilter string) error { 116 filter := "Name eq '" + v.Name + "' and TechRelease eq '" + v.TechRelease + "' and TechSpLevel eq '" + v.TechSpLevel + "' and ( " + statusFilter + " )" 117 orderBy := "TechPatchLevel desc" 118 119 if queryResuult, err := v.queryVersion(filter, orderBy); err != nil { 120 return err 121 } else { 122 if newPatchLevel, err := strconv.Atoi(queryResuult.TechPatchLevel); err != nil { 123 return err 124 } else { 125 v.TechPatchLevel = fmt.Sprintf("%04d", newPatchLevel+1) 126 return nil 127 } 128 } 129 } 130 131 func (v *versionable) queryVersion(filter string, orderBy string) (*versionable, error) { 132 result := versionable{} 133 134 values := url.Values{} 135 values.Set("$filter", filter) 136 values.Set("$orderby", orderBy) 137 values.Set("$select", "Name,Version,TechRelease,TechSpLevel,TechPatchLevel,Namespace") //Namespace needed otherwise empty result - will be fixed by OCS shortly 138 values.Set("$format", "json") 139 values.Set("$top", "1") 140 141 requestUrl := v.queryUrl + "?" + values.Encode() 142 143 if body, err := v.connector.Get(requestUrl); err != nil { 144 return &result, err 145 } else { 146 Versions := versionables{} 147 if err := json.Unmarshal(body, &Versions); err != nil { 148 return &result, errors.Wrap(err, "Unexpected AAKaaS response for Component Version Query: "+string(body)) 149 } 150 switch len(Versions.Wrapper.Vs) { 151 case 0: 152 result = versionable{ 153 TechRelease: "0", 154 TechSpLevel: "0000", 155 TechPatchLevel: "0000", 156 } 157 case 1: 158 result = Versions.Wrapper.Vs[0] 159 default: 160 return &result, errors.New("Unexpected Number of CVs in result: " + fmt.Sprint(len(Versions.Wrapper.Vs))) 161 } 162 } 163 log.Entry().Infof("... looked up highest existing package in AAKaaS of the codeline: %s.%s.%s", result.TechRelease, result.TechSpLevel, result.TechPatchLevel) 164 return &result, nil 165 } 166 167 func (v *versionable) getDottedVersionString() (string, error) { 168 var spLevelAsnumber int 169 var patchLevelAsNumber int 170 var err error 171 if spLevelAsnumber, err = strconv.Atoi(v.TechSpLevel); err != nil { 172 return "", err 173 } 174 if patchLevelAsNumber, err = strconv.Atoi(v.TechPatchLevel); err != nil { 175 return "", err 176 } 177 dottedVersionString := strings.Join([]string{v.TechRelease, strconv.Itoa(spLevelAsnumber), strconv.Itoa(patchLevelAsNumber)}, ".") 178 return dottedVersionString, nil 179 }