Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enforce bundle specs version to be semver #114

Merged
merged 2 commits into from
Jun 28, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions bundle/version.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
//
// Copyright (c) 2018 Red Hat, Inc.
//
// 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 bundle

import (
"github.com/coreos/go-semver/semver"
log "github.com/sirupsen/logrus"
)

// These constants describe the minimum and maximum
// accepted APB spec versions. They are used to filter
// acceptable APBs.

// MinSpecVersion constant to describe minimum supported spec version
const MinSpecVersion = "1.0.0"

// MaxSpecVersion constant to describe maximum supported spec version
const MaxSpecVersion = "1.0.0"

// These constants describe the minimum and maximum
// accepted APB runtime versions. They are used to filter
// acceptable APBs.

// MinRuntimeVersion constant to describe minimum supported runtime version
const MinRuntimeVersion = 1

// MaxRuntimeVersion constant to describe maximum supported runtime version
const MaxRuntimeVersion = 2

// The minimum/maximum Bundle spec semantic versions
var minSpecSemver = semver.New("1.0.0")
var maxSpecSemver = semver.New("1.0.0")

// ValidateVersion - Ensure the Bundle Spec Version and Bundle Runtime Version
// are within bounds
func (s *Spec) ValidateVersion() bool {
return s.checkVersion() && s.checkRuntime()
}

func (s *Spec) checkVersion() bool {
specSemver, err := semver.NewVersion(s.Version)
if err != nil {
if s.Version == "1.0" {
log.Warningf("Spec version is not semver compatable")
return true
}
log.Errorf("Failed to init semver - %v", err)
return false
}

if specSemver.Compare(*minSpecSemver) < 0 {
log.Errorf("Spec version (%v) is less than the minimum version %v", s.Version, MinSpecVersion)
return false
}

if specSemver.Compare(*maxSpecSemver) > 0 {
log.Errorf("Spec version (%v) is greater than the maximum version %v", s.Version, MaxSpecVersion)
return false
}

return true
}

func (s *Spec) checkRuntime() bool {
return s.Runtime >= MinRuntimeVersion && s.Runtime <= MaxRuntimeVersion
}
57 changes: 57 additions & 0 deletions bundle/version_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
//
// Copyright (c) 2018 Red Hat, Inc.
//
// 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 bundle

import (
//"fmt"
"testing"

ft "github.com/stretchr/testify/assert"
)

func TestValidateVersion(t *testing.T) {

// Test Valid Spec Version + Runtime Version
var testSpec = Spec{
Version: "1.0.0",
Runtime: 1,
}
ft.True(t, testSpec.ValidateVersion())

testSpec.Runtime = 2
ft.True(t, testSpec.ValidateVersion())

testSpec.Version = "1.0" // Deprecated Spec Version
ft.True(t, testSpec.ValidateVersion())

// Test Invalid Spec Versions
testSpec.Version = "0.9.0" // less than min
ft.False(t, testSpec.ValidateVersion())

testSpec.Version = "1.0.1" // greater than max
ft.False(t, testSpec.ValidateVersion())

testSpec.Version = "1.0.0" // back to valid version
ft.True(t, testSpec.ValidateVersion())

// Test Invalid Runtime Versions
testSpec.Runtime = 0
ft.False(t, testSpec.ValidateVersion()) // less than min

testSpec.Runtime = 3
ft.False(t, testSpec.ValidateVersion()) // greater than max
}
48 changes: 2 additions & 46 deletions registries/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (
"io/ioutil"
"net/url"
"regexp"
"strconv"
"strings"
"sync"

Expand Down Expand Up @@ -313,24 +312,8 @@ func validateSpecs(inSpecs []*bundle.Spec) []*bundle.Spec {
}

func validateSpecFormat(spec *bundle.Spec) (bool, string) {
// Specs must have compatible version
if !isCompatibleVersion(spec.Version, "1.0", "1.0") {
return false, fmt.Sprintf(
"APB Spec version [%v] out of bounds %v <= %v",
spec.Version,
"1.0",
"1.0",
)
}

// Specs must have compatible runtime version
if !isCompatibleRuntime(spec.Runtime, 1, 2) {
return false, fmt.Sprintf(
"APB Runtime version [%v] out of bounds %v <= %v",
spec.Runtime,
1,
2,
)
if !spec.ValidateVersion() {
return false, fmt.Sprintf("Spec [%v] failed version validation", spec.FQName)
}

// Specs must have at least one plan
Expand All @@ -352,33 +335,6 @@ func validateSpecFormat(spec *bundle.Spec) (bool, string) {
return true, ""
}

func isCompatibleVersion(specVersion string, minVersion string, maxVersion string) bool {
if len(strings.Split(specVersion, ".")) != 2 || len(strings.Split(minVersion, ".")) != 2 || len(strings.Split(maxVersion, ".")) != 2 {
return false
}
specMajorVersion, err := strconv.Atoi(strings.Split(specVersion, ".")[0])
if err != nil {
return false
}
minMajorVersion, err := strconv.Atoi(strings.Split(minVersion, ".")[0])
if err != nil {
return false
}
maxMajorVersion, err := strconv.Atoi(strings.Split(maxVersion, ".")[0])
if err != nil {
return false
}

if specMajorVersion >= minMajorVersion && specMajorVersion <= maxMajorVersion {
return true
}
return false
}

func isCompatibleRuntime(specRuntime int, minVersion int, maxVersion int) bool {
return specRuntime >= minVersion && specRuntime <= maxVersion
}

func retrieveRegistryAuth(reg Config, asbNamespace string) (Config, error) {
var username, password string
var err error
Expand Down
27 changes: 2 additions & 25 deletions registries/registry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ import (
var SpecTags = []string{"latest", "old-release"}

const SpecID = "ab094014-b740-495e-b178-946d5aa97ebf"
const SpecBadVersion = "2.0"
const SpecVersion = "1.0"
const SpecBadVersion = "2.0.0"
const SpecVersion = "1.0.0"
const SpecRuntime = 1
const SpecBadRuntime = 0
const SpecName = "etherpad-bundle"
Expand Down Expand Up @@ -397,29 +397,6 @@ func TestValidateName(t *testing.T) {
}
}

func TestVersionCheck(t *testing.T) {
// Test equal versions
ft.True(t, isCompatibleVersion("1.0", "1.0", "1.0"))
// Test out of range by major version
ft.False(t, isCompatibleVersion("2.0", "1.0", "1.0"))
// Test out of range by minor version
ft.True(t, isCompatibleVersion("1.10", "1.0", "1.0"))
// Test out of range by major and minor version
ft.True(t, isCompatibleVersion("2.4", "1.0", "2.0"))
// Test in range with differing major and minor version
ft.True(t, isCompatibleVersion("1.10", "1.0", "2.0"))
// Test out of range by major and minor version
ft.False(t, isCompatibleVersion("0.6", "1.0", "2.0"))
// Test out of range by major and minor version and invalid version
ft.False(t, isCompatibleVersion("0.1.0", "1.0", "1.0"))
// Test in range of long possible window
ft.True(t, isCompatibleVersion("2.5", "1.0", "3.0"))
// Test invalid version
ft.False(t, isCompatibleVersion("1", "1.0", "3.0"))
// Test invalid version
ft.False(t, isCompatibleVersion("2.5", "3.0", "4.0"))
}

type fakeAdapter struct{}

func (f fakeAdapter) GetImageNames() ([]string, error) {
Expand Down