generated from cloudnative-pg/cnpg-template
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: types/functions for images and Postgres versions (#29)
Signed-off-by: Leonardo Cecchi <leonardo.cecchi@enterprisedb.com> Signed-off-by: Francesco Canovai <francesco.canovai@enterprisedb.com> Signed-off-by: Gabriele Bartolini <gabriele.bartolini@enterprisedb.com> Co-authored-by: Gabriele Bartolini <gabriele.bartolini@enterprisedb.com>
- Loading branch information
1 parent
8b1bd3e
commit 34c8797
Showing
8 changed files
with
461 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/* | ||
Copyright The CloudNativePG Contributors | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
// Package reference contains an image reference | ||
// parser | ||
package reference |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
/* | ||
Copyright The CloudNativePG Contributors | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package reference | ||
|
||
import ( | ||
"fmt" | ||
"regexp" | ||
"strings" | ||
) | ||
|
||
var ( | ||
digestRegex = regexp.MustCompile(`@sha256:(?P<sha256>[a-fA-F0-9]+)$`) | ||
tagRegex = regexp.MustCompile(`:(?P<tag>[^/]+)$`) | ||
hostRegex = regexp.MustCompile(`^[^./:]+((\.[^./:]+)+(:[0-9]+)?|:[0-9]+)/`) | ||
) | ||
|
||
// Data is the main data type | ||
type Data struct { | ||
Name string | ||
Tag string | ||
Digest string | ||
} | ||
|
||
// GetNormalizedName returns the normalized name of a reference | ||
func (r *Data) GetNormalizedName() (name string) { | ||
name = r.Name | ||
if r.Tag != "" { | ||
name = fmt.Sprintf("%s:%s", name, r.Tag) | ||
} | ||
if r.Digest != "" { | ||
name = fmt.Sprintf("%s@sha256:%s", name, r.Digest) | ||
} | ||
return name | ||
} | ||
|
||
// New parses the image name and returns an error if the name is invalid. | ||
func New(name string) *Data { | ||
reference := &Data{} | ||
|
||
if !strings.Contains(name, "/") { | ||
name = "docker.io/library/" + name | ||
} else if !hostRegex.MatchString(name) { | ||
name = "docker.io/" + name | ||
} | ||
|
||
if digestRegex.MatchString(name) { | ||
res := digestRegex.FindStringSubmatch(name) | ||
reference.Digest = res[1] // digest capture group index | ||
name = strings.TrimSuffix(name, res[0]) | ||
} | ||
|
||
if tagRegex.MatchString(name) { | ||
res := tagRegex.FindStringSubmatch(name) | ||
reference.Tag = res[1] // tag capture group index | ||
name = strings.TrimSuffix(name, res[0]) | ||
} else if reference.Digest == "" { | ||
reference.Tag = "latest" | ||
} | ||
|
||
// everything else is the name | ||
reference.Name = name | ||
|
||
return reference | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
/* | ||
Copyright The CloudNativePG Contributors | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package reference | ||
|
||
import ( | ||
. "github.com/onsi/ginkgo/v2" | ||
. "github.com/onsi/gomega" | ||
) | ||
|
||
var _ = Describe("image name management", func() { | ||
It("should normalize image names", func() { | ||
Expect(New("postgres").GetNormalizedName()).To( | ||
Equal("docker.io/library/postgres:latest")) | ||
Expect(New("myimage/postgres").GetNormalizedName()).To( | ||
Equal("docker.io/myimage/postgres:latest")) | ||
Expect(New("localhost:5000/postgres").GetNormalizedName()).To( | ||
Equal("localhost:5000/postgres:latest")) | ||
Expect(New("registry.localhost:5000/postgres:14.4").GetNormalizedName()).To( | ||
Equal("registry.localhost:5000/postgres:14.4")) | ||
Expect(New("ghcr.io/cloudnative-pg/postgresql:34").GetNormalizedName()).To( | ||
Equal("ghcr.io/cloudnative-pg/postgresql:34")) | ||
}) | ||
|
||
It("should extract tag names", func() { | ||
Expect(New("postgres").Tag).To(Equal("latest")) | ||
Expect(New("postgres:34.3").Tag).To(Equal("34.3")) | ||
Expect(New("postgres:13@sha256:cff94de382ca538861622bbe84cfe03f44f307a9846a5c5eda672cf4dc692866").Tag). | ||
To(Equal("13")) | ||
}) | ||
|
||
It("should not extract a tag name", func() { | ||
Expect(New("postgres@sha256:cff94dd382ca538861622bbe84cfe03f44f307a9846a5c5eda672cf4dc692866").Tag). | ||
To(BeEmpty()) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
/* | ||
Copyright The CloudNativePG Contributors | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package reference | ||
|
||
import ( | ||
"testing" | ||
|
||
. "github.com/onsi/ginkgo/v2" | ||
. "github.com/onsi/gomega" | ||
) | ||
|
||
// These tests use Ginkgo (BDD-style Go testing framework). Refer to | ||
// http://onsi.github.io/ginkgo/ to learn more about Ginkgo. | ||
|
||
func TestPostgresVersion(t *testing.T) { | ||
RegisterFailHandler(Fail) | ||
|
||
RunSpecs(t, "PostgreSQL Version") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/* | ||
Copyright The CloudNativePG Contributors | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
// Package version contains a PostgreSQL image version parser with | ||
// the corresponding data type and operations on it | ||
package version |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
/* | ||
Copyright The CloudNativePG Contributors | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package version | ||
|
||
import ( | ||
"testing" | ||
|
||
. "github.com/onsi/ginkgo/v2" | ||
. "github.com/onsi/gomega" | ||
) | ||
|
||
// These tests use Ginkgo (BDD-style Go testing framework). Refer to | ||
// http://onsi.github.io/ginkgo/ to learn more about Ginkgo. | ||
|
||
func TestPostgresVersion(t *testing.T) { | ||
RegisterFailHandler(Fail) | ||
|
||
RunSpecs(t, "PostgreSQL Version") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
/* | ||
Copyright The CloudNativePG Contributors | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package version | ||
|
||
import ( | ||
"fmt" | ||
"math" | ||
"regexp" | ||
"strconv" | ||
"strings" | ||
) | ||
|
||
var semanticVersionRegex = regexp.MustCompile(`^(\d\.?)+`) | ||
|
||
// Data is a structure used to manage a PostgreSQL version, | ||
// consisting of two parts: major and minor. For instance, | ||
// version 10.0 corresponds to a major of 10 and a minor of 0. | ||
// See: https://www.postgresql.org/support/versioning/ | ||
type Data struct { | ||
major uint64 | ||
minor uint64 | ||
} | ||
|
||
// Major gets the major version (i.e. 10) | ||
func (d Data) Major() uint64 { | ||
return d.major | ||
} | ||
|
||
// Minor gets the minor version (i.e. 0) | ||
func (d Data) Minor() uint64 { | ||
return d.minor | ||
} | ||
|
||
// Less is the implementation of the "less than" operator | ||
func (d Data) Less(other Data) bool { | ||
if d.major < other.major { | ||
return true | ||
} else if d.major > other.major { | ||
return false | ||
} | ||
|
||
return d.minor < other.minor | ||
} | ||
|
||
// New constructs a version from its components | ||
func New(major, minor uint64) Data { | ||
return Data{ | ||
major: major, | ||
minor: minor, | ||
} | ||
} | ||
|
||
// FromTag parse a PostgreSQL version string returning | ||
// a major version ID. Example: | ||
// | ||
// FromTag("11.2") == (11,2) | ||
// FromTag("12.1") == (12,1) | ||
// FromTag("13.3.2.1-1") == (13,3) | ||
// FromTag("13.4") == (13,4) | ||
// FromTag("14") == (14,0) | ||
// FromTag("15.5-10") == (15,5) | ||
// FromTag("16.0") == (16,0) | ||
// FromTag("17beta1") == (17,0) | ||
// FromTag("17rc1") == (17,0) | ||
func FromTag(version string) (Data, error) { | ||
if !semanticVersionRegex.MatchString(version) { | ||
return Data{}, | ||
fmt.Errorf("version not starting with a semantic version regex (%v): %s", semanticVersionRegex, version) | ||
} | ||
|
||
if versionOnly := semanticVersionRegex.FindString(version); versionOnly != "" { | ||
version = versionOnly | ||
} | ||
|
||
splitVersion := strings.Split(version, ".") | ||
|
||
majorVersion, err := strconv.Atoi(splitVersion[0]) | ||
if err != nil { | ||
return Data{}, fmt.Errorf("wrong PostgreSQL major in version %v", version) | ||
} | ||
|
||
minorVersion := 0 | ||
if len(splitVersion) > 1 { | ||
minorVersion, err = strconv.Atoi(splitVersion[1]) | ||
if err != nil { | ||
return Data{}, fmt.Errorf("wrong PostgreSQL minor in version %v", version) | ||
} | ||
} | ||
|
||
if majorVersion < 0 || majorVersion > math.MaxInt { | ||
return Data{}, fmt.Errorf("wrong PostgreSQL major in version %v", version) | ||
} | ||
|
||
if minorVersion < 0 || minorVersion > math.MaxInt { | ||
return Data{}, fmt.Errorf("wrong PostgreSQL minor in version %v", version) | ||
} | ||
|
||
return Data{ | ||
major: uint64(majorVersion), | ||
minor: uint64(minorVersion), | ||
}, nil | ||
} | ||
|
||
// IsUpgradePossible detect if it's possible to upgrade from fromVersion to | ||
// toVersion | ||
func IsUpgradePossible(fromVersion, toVersion Data) bool { | ||
return fromVersion.major == toVersion.major | ||
} |
Oops, something went wrong.