Skip to content
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
59 changes: 48 additions & 11 deletions client/channel.go
Original file line number Diff line number Diff line change
Expand Up @@ -230,12 +230,7 @@ func (c *Client) GetCurrentChannelRelease(appID string, appType string, channelI

// If the channel has releases data, find the current one
if len(kotsChannel.Releases) > 0 {
var currentRelease *types.ChannelRelease
for _, release := range kotsChannel.Releases {
if currentRelease == nil || release.ChannelSequence > currentRelease.ChannelSequence {
currentRelease = &release
}
}
currentRelease := currentChannelRelease(kotsChannel.Releases, kotsChannel.ChannelSequence)
if currentRelease != nil {
proxyDomain := currentRelease.ProxyRegistryDomain
if proxyDomain == "" && kotsChannel.CustomHostNameOverrides.Proxy.Hostname != "" {
Expand All @@ -257,6 +252,7 @@ func (c *Client) GetCurrentChannelRelease(appID string, appType string, channelI
}
return currentRelease, proxyDomain, nil
}
return nil, "", errors.New("no active releases found in channel")
}

// Fallback to the existing approach if releases aren't included
Expand All @@ -269,11 +265,9 @@ func (c *Client) GetCurrentChannelRelease(appID string, appType string, channelI
return nil, "", errors.New("no releases found in channel")
}

var currentRelease *types.ChannelRelease
for _, release := range releases {
if currentRelease == nil || release.ChannelSequence > currentRelease.ChannelSequence {
currentRelease = release
}
currentRelease := currentChannelReleasePtrs(releases, kotsChannel.ChannelSequence)
if currentRelease == nil {
return nil, "", errors.New("no active releases found in channel")
}

proxyDomain := currentRelease.ProxyRegistryDomain
Expand All @@ -300,6 +294,49 @@ func (c *Client) GetCurrentChannelRelease(appID string, appType string, channelI
return nil, "", errors.Errorf("unknown app type %q", appType)
}

// currentChannelRelease returns the release matching channelSequence (the server's
// authoritative current sequence). Falls back to the highest non-demoted sequence
// when channelSequence is 0 (not returned by the API).
func currentChannelRelease(releases []types.ChannelRelease, channelSequence int32) *types.ChannelRelease {
if channelSequence > 0 {
for i := range releases {
if releases[i].ChannelSequence == channelSequence {
return &releases[i]
}
}
}
var currentRelease *types.ChannelRelease
for i := range releases {
if releases[i].IsDemoted {
continue
}
if currentRelease == nil || releases[i].ChannelSequence > currentRelease.ChannelSequence {
currentRelease = &releases[i]
}
}
return currentRelease
}

func currentChannelReleasePtrs(releases []*types.ChannelRelease, channelSequence int32) *types.ChannelRelease {
if channelSequence > 0 {
for _, release := range releases {
if release != nil && release.ChannelSequence == channelSequence {
return release
}
}
}
var currentRelease *types.ChannelRelease
for _, release := range releases {
if release == nil || release.IsDemoted {
continue
}
if currentRelease == nil || release.ChannelSequence > currentRelease.ChannelSequence {
currentRelease = release
}
}
return currentRelease
}

// GetDefaultProxyHostname gets the default proxy hostname from the app's custom hostnames
func (c *Client) GetDefaultProxyHostname(appID string) (string, error) {
customHostnames, err := c.KotsClient.ListCustomHostnames(appID)
Expand Down
80 changes: 80 additions & 0 deletions client/channel_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package client

import (
"testing"

"github.com/replicatedhq/replicated/pkg/types"
"github.com/stretchr/testify/require"
)

func TestCurrentChannelReleaseUsesChannelSequence(t *testing.T) {
releases := []types.ChannelRelease{
{ChannelSequence: 1},
{ChannelSequence: 2},
{ChannelSequence: 3, IsDemoted: true},
}

currentRelease := currentChannelRelease(releases, 2)

require.NotNil(t, currentRelease)
require.EqualValues(t, 2, currentRelease.ChannelSequence)
}

func TestCurrentChannelReleaseSkipsDemotedReleases(t *testing.T) {
releases := []types.ChannelRelease{
{ChannelSequence: 1},
{ChannelSequence: 2, IsDemoted: true},
}

currentRelease := currentChannelRelease(releases, 0)

require.NotNil(t, currentRelease)
require.EqualValues(t, 1, currentRelease.ChannelSequence)
}

func TestCurrentChannelReleaseReturnsNilWhenAllReleasesAreDemoted(t *testing.T) {
releases := []types.ChannelRelease{
{ChannelSequence: 1, IsDemoted: true},
{ChannelSequence: 2, IsDemoted: true},
}

currentRelease := currentChannelRelease(releases, 0)

require.Nil(t, currentRelease)
}

func TestCurrentChannelReleasePtrsUsesChannelSequence(t *testing.T) {
releases := []*types.ChannelRelease{
{ChannelSequence: 1},
{ChannelSequence: 2},
{ChannelSequence: 3, IsDemoted: true},
}

currentRelease := currentChannelReleasePtrs(releases, 2)

require.NotNil(t, currentRelease)
require.EqualValues(t, 2, currentRelease.ChannelSequence)
}

func TestCurrentChannelReleasePtrsSkipsDemotedReleases(t *testing.T) {
releases := []*types.ChannelRelease{
{ChannelSequence: 1},
{ChannelSequence: 2, IsDemoted: true},
}

currentRelease := currentChannelReleasePtrs(releases, 0)

require.NotNil(t, currentRelease)
require.EqualValues(t, 1, currentRelease.ChannelSequence)
}

func TestCurrentChannelReleasePtrsReturnsNilWhenAllReleasesAreDemoted(t *testing.T) {
releases := []*types.ChannelRelease{
{ChannelSequence: 1, IsDemoted: true},
{ChannelSequence: 2, IsDemoted: true},
}

currentRelease := currentChannelReleasePtrs(releases, 0)

require.Nil(t, currentRelease)
}