@@ -241,7 +241,12 @@ func (i *OperatorInstall) createSubscription(ctx context.Context, pm *operator.P
241
241
}
242
242
243
243
if i .Version != "" {
244
- guessedStartingCSV := guessStartingCSV (pc .CurrentCSV , i .Version )
244
+ // Use the CSV name of the channel head as a template to guess the CSV name based on
245
+ // the desired version.
246
+ guessedStartingCSV , err := guessStartingCSV (pc .CurrentCSV , i .Version )
247
+ if err != nil {
248
+ return nil , fmt .Errorf ("could not guess startingCSV: %v" , err )
249
+ }
245
250
opts = append (opts , subscription .StartingCSV (guessedStartingCSV ))
246
251
}
247
252
@@ -261,23 +266,20 @@ func (i *OperatorInstall) createSubscription(ctx context.Context, pm *operator.P
261
266
return sub , nil
262
267
}
263
268
264
- func guessStartingCSV (csvNameExample , desiredVersion string ) string {
265
- csvBaseName , vChar , _ := parseCSVName (csvNameExample )
266
- version := strings .TrimPrefix (desiredVersion , "v" )
267
- return fmt .Sprintf ("%s.%s%s" , csvBaseName , vChar , version )
269
+ // guessStartingCSV finds the first semver version string in csvNameExample, and replaces all
270
+ // occurrences with desiredVersion, trimming any "v" prefix from desiredVersion prior to making the
271
+ // replacements. If csvNameExample does not contain a semver version string, guessStartingCSV
272
+ // returns an error.
273
+ func guessStartingCSV (csvNameExample , desiredVersion string ) (string , error ) {
274
+ exampleVersion := semverRegexp .FindString (csvNameExample )
275
+ if exampleVersion == "" {
276
+ return "" , fmt .Errorf ("could not locate semver version in channel head CSV name %q" , csvNameExample )
277
+ }
278
+ desiredVersion = strings .TrimPrefix (desiredVersion , "v" )
279
+ return strings .ReplaceAll (csvNameExample , exampleVersion , desiredVersion ), nil
268
280
}
269
281
270
- const (
271
- operatorNameRegexp = `[a-z0-9]([-a-z0-9]*[a-z0-9])?`
272
- semverRegexp = `(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)(?:-(?P<prerelease>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?` //nolint:lll
273
- )
274
-
275
- var csvNameRegexp = regexp .MustCompile (`^(` + operatorNameRegexp + `).(v?)(` + semverRegexp + `)$` )
276
-
277
- func parseCSVName (csvName string ) (string , string , string ) {
278
- matches := csvNameRegexp .FindAllStringSubmatch (csvName , - 1 )
279
- return matches [0 ][1 ], matches [0 ][3 ], matches [0 ][4 ]
280
- }
282
+ var semverRegexp = regexp .MustCompile (`(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)(?:-(?P<prerelease>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?` ) //nolint:lll
281
283
282
284
func (i * OperatorInstall ) getInstallPlan (ctx context.Context , sub * v1alpha1.Subscription ) (* v1alpha1.InstallPlan , error ) {
283
285
subKey := objectKeyForObject (sub )
0 commit comments