Skip to content

Commit

Permalink
Add hash mode compatibility
Browse files Browse the repository at this point in the history
Signed-off-by: Aniruddha Basak <aniruddha.basak@syself.com>
  • Loading branch information
aniruddha2000 committed Jan 19, 2024
1 parent 8d168d7 commit f36a4f7
Show file tree
Hide file tree
Showing 12 changed files with 221 additions and 59 deletions.
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

0 comments on commit f36a4f7

Please sign in to comment.