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

✨ Add hash mode compatibility #53

Merged
merged 1 commit into from
Jan 19, 2024
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
2 changes: 1 addition & 1 deletion api/v1alpha1/clusterstack_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ type ClusterStackSpec struct {

// Channel specifies the release channel of the cluster stack. Defaults to 'stable'.
// +kubebuilder:default:=stable
// +kubebuilder:validation:enum=stable;alpha;beta;rc
// +kubebuilder:validation:Enum=stable;custom
Channel version.Channel `json:"channel,omitempty"`

// Versions is a list of version of the cluster stack that should be available in the management cluster.
Expand Down
3 changes: 3 additions & 0 deletions config/crd/bases/clusterstack.x-k8s.io_clusterstacks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ spec:
default: stable
description: Channel specifies the release channel of the cluster
stack. Defaults to 'stable'.
enum:
- stable
- custom
type: string
kubernetesVersion:
description: KubernetesVersion is the Kubernetes version in the format
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ require (
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.1 // indirect
gopkg.in/yaml.v3 v3.0.1
k8s.io/apiextensions-apiserver v0.27.2
k8s.io/apiserver v0.27.2 // indirect
k8s.io/component-base v0.27.2 // indirect
Expand Down
19 changes: 8 additions & 11 deletions hack/kind-dev.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,29 +24,26 @@ REPO_ROOT=$(git rev-parse --show-toplevel)
cd "${REPO_ROOT}" || exit 1

# Creates a kind cluster with the ctlptl tool https://github.com/tilt-dev/ctlptl
ctlptl_kind-cluster-with-registry () {

local CLUSTER_NAME=$1
local CLUSTER_VERSION=$2
ctlptl_kind-cluster-with-registry() {

cat <<EOF | ctlptl apply -f -
local CLUSTER_NAME=$1
local CLUSTER_VERSION=$2

cat <<EOF | ctlptl apply -f -
apiVersion: ctlptl.dev/v1alpha1
kind: Registry
name: ${CLUSTER_NAME}-registry
name: kind-registry
port: 5000
---
apiVersion: ctlptl.dev/v1alpha1
kind: Cluster
product: kind
registry: ${CLUSTER_NAME}-registry
registry: kind-registry
kindV1Alpha4Cluster:
name: ${CLUSTER_NAME}
nodes:
- role: control-plane
image: kindest/node:${CLUSTER_VERSION}
extraMounts:
- hostPath: /var/run/docker.sock
containerPath: /var/run/docker.sock
networking:
podSubnet: "10.244.0.0/16"
serviceSubnet: "10.96.0.0/12"
Expand All @@ -64,4 +61,4 @@ ctlptl_kind-cluster-with-registry cso ${K8S_VERSION}
echo ""
echo ""
echo ""
echo "Cluster is ready - you can now tilt up!"
echo "Cluster is ready - you can now tilt up!"
2 changes: 1 addition & 1 deletion internal/clusterstackrelease/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import (

// Summary returns a ClusterStackReleaseSummary object from a clusterStackRelease.
func Summary(csr *csov1alpha1.ClusterStackRelease) (csov1alpha1.ClusterStackReleaseSummary, error) {
clusterStack, err := clusterstack.NewFromString(csr.Name)
clusterStack, err := clusterstack.NewFromClusterStackReleaseProperties(csr.Name)
if err != nil {
return csov1alpha1.ClusterStackReleaseSummary{}, fmt.Errorf("failed to create clusterStack from string %s: %w", csr.Name, err)
}
Expand Down
2 changes: 1 addition & 1 deletion internal/controller/clusteraddon_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ func (r *ClusterAddonReconciler) Reconcile(ctx context.Context, req reconcile.Re
// cluster is ready, so we set a condition and can continue as well
conditions.MarkTrue(clusterAddon, csov1alpha1.ClusterReadyCondition)

releaseAsset, download, err := release.New(cluster.Spec.Topology.Class, r.ReleaseDirectory)
releaseAsset, download, err := release.New(release.ConvertFromClusterClassToClusterStackFormat(cluster.Spec.Topology.Class), r.ReleaseDirectory)
if err != nil {
conditions.MarkFalse(clusterAddon, csov1alpha1.ClusterStackReleaseAssetsReadyCondition, csov1alpha1.IssueWithReleaseAssetsReason, clusterv1.ConditionSeverityError, err.Error())
return ctrl.Result{RequeueAfter: 10 * time.Second}, nil
Expand Down
4 changes: 2 additions & 2 deletions internal/controller/clusterstack_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ func getLatestReadyClusterStackRelease(clusterStackReleases []*csov1alpha1.Clust
// filter the ones that are ready
for _, csr := range clusterStackReleases {
if csr.Status.Ready {
cs, err := clusterstack.NewFromString(csr.Name)
cs, err := clusterstack.NewFromClusterStackReleaseProperties(csr.Name)
if err != nil {
return nil, "", fmt.Errorf("failed to get clusterstack from ClusterStackRelease.Name %q: %w", csr.Name, err)
}
Expand Down Expand Up @@ -624,7 +624,7 @@ func matchesOwnerRef(a *metav1.OwnerReference, clusterStack *csov1alpha1.Cluster
}

func matchesSpec(str string, spec *csov1alpha1.ClusterStackSpec) (clusterstack.ClusterStack, bool, error) {
csObject, err := clusterstack.NewFromString(str)
csObject, err := clusterstack.NewFromClusterStackReleaseProperties(str)
if err != nil {
return clusterstack.ClusterStack{}, false, fmt.Errorf("failed to get clusterstack object from string %q: %w", str, err)
}
Expand Down
2 changes: 1 addition & 1 deletion internal/controller/clusterstack_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ func TestGetClusterStackReleasesInSpec(t *testing.T) {
Provider: "docker",
Name: "ferrol",
KubernetesVersion: "1.21",
Versions: []string{"v1", "v2", "v3-alpha-0"},
Versions: []string{"v1", "v2", "v3-alpha.0"},
}

result, err := getClusterStackReleasesInSpec(spec)
Expand Down
59 changes: 55 additions & 4 deletions pkg/clusterstack/clusterstack.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,57 @@ var (
ErrInvalidName = fmt.Errorf("invalid name")
)

// NewFromString returns a ClusterStack based on a cluster stack string.
func NewFromString(str string) (ClusterStack, error) {
// NewFromClusterClassProperties returns a ClusterStack based on a cluster stack string.
// e.g. - "docker-ferrol-1-27-v1", "docker-ferrol-1-27-v1-alpha.1", etc.
func NewFromClusterClassProperties(str string) (ClusterStack, error) {
splitted := strings.Split(str, Separator)
if len(splitted) != 5 && len(splitted) != 6 {
return ClusterStack{}, ErrInvalidFormat
}

clusterStack := ClusterStack{
Provider: splitted[0],
Name: splitted[1],
}

if clusterStack.Provider == "" {
return ClusterStack{}, ErrInvalidProvider
}

if clusterStack.Name == "" {
return ClusterStack{}, ErrInvalidName
}

var err error

clusterStack.KubernetesVersion, err = kubernetesversion.New(splitted[2], splitted[3])
if err != nil {
return ClusterStack{}, fmt.Errorf("failed to create Kubernetes version from %s-%s: %w", splitted[2], splitted[3], err)
}

var versionString string
if len(splitted) == 5 {
// e.g. myprovider-myclusterstack-1-26-v1
versionString = splitted[4]
} else if len(splitted) == 6 {
// e.g. myprovider-myclusterstack-1-26-v1-alpha.0
versionString = strings.Join(splitted[4:6], Separator)
}

// version string like v1-alpha.0
v, err := version.New(versionString)
if err != nil {
return ClusterStack{}, fmt.Errorf("failed to create version from %s: %w", versionString, err)
}

clusterStack.Version = v

return clusterStack, nil
}

// NewFromClusterStackReleaseProperties returns a ClusterStack based on a cluster stack string.
// e.g. - "docker-ferrol-1-27-v1", "docker-ferrol-1-27-v1-alpha-1", etc.
func NewFromClusterStackReleaseProperties(str string) (ClusterStack, error) {
splitted := strings.Split(str, Separator)
if len(splitted) != 5 && len(splitted) != 7 {
return ClusterStack{}, ErrInvalidFormat
Expand Down Expand Up @@ -91,7 +140,8 @@ func NewFromString(str string) (ClusterStack, error) {
versionString = strings.Join(splitted[4:7], Separator)
}

v, err := version.New(versionString)
// version string like v1-alpha-0
v, err := version.ParseVersionString(versionString)
if err != nil {
return ClusterStack{}, fmt.Errorf("failed to create version from %s: %w", versionString, err)
}
Expand All @@ -101,7 +151,8 @@ func NewFromString(str string) (ClusterStack, error) {
return clusterStack, nil
}

// New returns a ClusterStack based on a cluster stack string.
// New returns a ClusterStack based on a cluster stack properties and the version is in the form of -
// "v1", "v1-alpha.1", etc.
func New(provider, name, kubernetesVersion, csVersion string) (ClusterStack, error) {
k8sVersion, err := kubernetesversion.NewFromString(kubernetesVersion)
if err != nil {
Expand Down
45 changes: 40 additions & 5 deletions pkg/release/release.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ import (
"strings"

"github.com/SovereignCloudStack/cluster-stack-operator/pkg/clusterstack"
"gopkg.in/yaml.v2"
"github.com/SovereignCloudStack/cluster-stack-operator/pkg/version"
"gopkg.in/yaml.v3"
)

// Release contains information for ClusterStack release.
Expand Down Expand Up @@ -57,8 +58,9 @@ const (
func New(tag, downloadPath string) (Release, bool, error) {
// downloadPath is the path where the release is downloaded.
// The path is of the form: <downloadPath>/<clusterStackSuffix>/<tag>/
// For example: /tmp/downloads/cluster-stacks/docker-ferrol-1-26-v2/
downloadPath = filepath.Join(downloadPath, clusterStackSuffix, tag)
cs, err := clusterstack.NewFromString(tag)
cs, err := clusterstack.NewFromClusterStackReleaseProperties(tag)
if err != nil {
return Release{}, false, fmt.Errorf("failed to parse cluster stack release: %w", err)
}
Expand Down Expand Up @@ -92,6 +94,18 @@ func New(tag, downloadPath string) (Release, bool, error) {
return rel, false, nil
}

// ConvertFromClusterClassToClusterStackFormat converts `docker-ferrol-1-27-v0-sha.3960147` way to
// `docker-ferrol-1-27-v0-sha-3960147`.
func ConvertFromClusterClassToClusterStackFormat(input string) string {
parts := strings.Split(input, ".")

if len(parts) == 2 {
return fmt.Sprintf("%s-%s", parts[0], parts[1])
}

return input
}

func ensureMetadata(downloadPath, metadataFileName string) (Metadata, error) {
// Read the metadata.yaml file from the release.
metadataPath := filepath.Join(downloadPath, metadataFileName)
Expand All @@ -107,6 +121,25 @@ func ensureMetadata(downloadPath, metadataFileName string) (Metadata, error) {
return Metadata{}, fmt.Errorf("failed to unmarshal metadata: %w", err)
}

// Normalize the versions of metadata from v1-alpha.1 to v1-alpha-1 format.
metaClusterStackVersion, err := version.New(metadata.Versions.ClusterStack)
if err != nil {
return Metadata{}, fmt.Errorf("failed to parse ClusterStack version from metadata: %w", err)
}
metadata.Versions.ClusterStack = metaClusterStackVersion.String()

metaClusterAddonVersion, err := version.New(metadata.Versions.Components.ClusterAddon)
if err != nil {
return Metadata{}, fmt.Errorf("failed to parse ClusterAddon version from metadata: %w", err)
}
metadata.Versions.Components.ClusterAddon = metaClusterAddonVersion.String()

metaNodeImageVersion, err := version.New(metadata.Versions.Components.NodeImage)
if err != nil {
return Metadata{}, fmt.Errorf("failed to parse NodeImage version from metadata: %w", err)
}
metadata.Versions.Components.NodeImage = metaNodeImageVersion.String()

return metadata, nil
}

Expand Down Expand Up @@ -165,13 +198,15 @@ func (r *Release) Validate() error {

// clusterAddonChartName returns the helm chart name for cluster addon.
func (r *Release) clusterAddonChartName() string {
return fmt.Sprintf("%s-%s-%s-cluster-addon-%s", r.ClusterStack.Provider, r.ClusterStack.Name, r.ClusterStack.KubernetesVersion, r.Meta.Versions.Components.ClusterAddon)
clusterAddonVersion, _ := version.ParseVersionString(r.Meta.Versions.Components.ClusterAddon)
return fmt.Sprintf("%s-%s-%s-cluster-addon-%s", r.ClusterStack.Provider, r.ClusterStack.Name, r.ClusterStack.KubernetesVersion, clusterAddonVersion.StringWithDot())
}

// ClusterAddonChartPath returns the helm chart name from the given path.
func (r *Release) ClusterAddonChartPath() string {
// we ignore the error here, since we already checked for the presence of the chart.
path, _ := r.helmChartNamePath(r.clusterAddonChartName())
name := r.clusterAddonChartName()
path, _ := r.helmChartNamePath(name)
return path
}

Expand All @@ -182,7 +217,7 @@ func (r *Release) ClusterAddonValuesPath() string {

// clusterClassChartName returns the helm chart name for cluster class.
func (r *Release) clusterClassChartName() string {
return fmt.Sprintf("%s-%s-%s-cluster-class-%s", r.ClusterStack.Provider, r.ClusterStack.Name, r.ClusterStack.KubernetesVersion, r.ClusterStack.Version.String())
return fmt.Sprintf("%s-%s-%s-cluster-class-%s", r.ClusterStack.Provider, r.ClusterStack.Name, r.ClusterStack.KubernetesVersion, r.ClusterStack.Version.StringWithDot())
}

// ClusterClassChartPath returns the absolute helm chart path for cluster class.
Expand Down
12 changes: 3 additions & 9 deletions pkg/version/channel.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,12 @@ type Channel string
const (
// ChannelStable is the stable channel.
ChannelStable = Channel("stable")
// ChannelAlpha is the alpha channel.
ChannelAlpha = Channel("alpha")
// ChannelBeta is the beta channel.
ChannelBeta = Channel("beta")
// ChannelRC is the rc channel.
ChannelRC = Channel("rc")
// ChannelCustom is the custom channel where git hash is used in the versioning.
ChannelCustom = Channel("custom")
)

// IsValid returns true if the release channel is valid.
func (c Channel) IsValid() bool {
return c == ChannelStable ||
c == ChannelAlpha ||
c == ChannelBeta ||
c == ChannelRC
c == ChannelCustom
}
Loading
Loading