nvidia-container-toolkit/internal/requirements/constraints/property.go

131 lines
3.2 KiB
Go
Raw Normal View History

/**
# Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
#
# 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 constraints
import (
"fmt"
"strings"
"golang.org/x/mod/semver"
)
// Property represents a property that is used to check requirements
//
//go:generate moq -stub -out property_mock.go . Property
type Property interface {
Name() string
Value() (string, error)
String() string
CompareTo(string) (int, error)
Validate(string) error
}
// NewStringProperty creates a string property based on the name-value pair
func NewStringProperty(name string, value string) Property {
p := stringProperty{
name: name,
value: value,
}
return p
}
// NewVersionProperty creates a property representing a semantic version based on the name-value pair
func NewVersionProperty(name string, value string) Property {
p := versionProperty{
stringProperty: stringProperty{
name: name,
value: value,
},
}
return p
}
// stringProperty represents a property that is used to check requirements
type stringProperty struct {
name string
value string
}
type versionProperty struct {
stringProperty
}
// Name returns a stringProperty's name
func (p stringProperty) Name() string {
return p.name
}
// Value returns a stringProperty's value or an error if this cannot be determined
func (p stringProperty) Value() (string, error) {
return p.value, nil
}
// CompareTo compares two strings to each other
func (p stringProperty) CompareTo(other string) (int, error) {
value := p.value
if value < other {
return -1, nil
}
if value > other {
return 1, nil
}
return 0, nil
}
// Validate returns nil for all input strings
func (p stringProperty) Validate(string) error {
return nil
}
// String returns the string representation of the name value combination
func (p stringProperty) String() string {
v, err := p.Value()
if err != nil {
return fmt.Sprintf("invalid %v: %v", p.name, err)
}
return fmt.Sprintf("%v=%v", p.name, v)
}
// CompareTo compares two versions to each other as semantic versions
func (p versionProperty) CompareTo(other string) (int, error) {
if err := p.Validate(other); err != nil {
return 0, fmt.Errorf("invailid value for %v: %v", p.name, err)
}
vValue := ensurePrefix(p.value, "v")
vOther := ensurePrefix(other, "v")
return semver.Compare(vValue, vOther), nil
}
// Validate checks whether the supplied value is a valid semantic version
func (p versionProperty) Validate(value string) error {
if !semver.IsValid(ensurePrefix(value, "v")) {
return fmt.Errorf("invailid value %v; expected a valid version string", value)
}
return nil
}
func ensurePrefix(s string, prefix string) string {
return prefix + strings.TrimPrefix(s, prefix)
}