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

Added check for update in any mandatory release of karmor CLI #251

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
8 changes: 5 additions & 3 deletions selfupdate/selfupdate.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ var BuildDate string

const ghrepo = "kubearmor/kubearmor-client"

func isValidVersion(ver string) bool {
// IsValidVersion checks if a given string is a valid semantic version.
// Returns true if the string is a valid semantic version, false otherwise.
func IsValidVersion(ver string) bool {
_, err := semver.Make(ver)
return err == nil
}
Expand Down Expand Up @@ -59,7 +61,7 @@ func getLatest() (*selfupdate.Release, error) {

// IsLatest - check if the current binary is the latest
func IsLatest(curver string) (bool, string) {
if curver != "" && !isValidVersion(curver) {
if curver != "" && !IsValidVersion(curver) {
return true, ""
}
latest, err := getLatest()
Expand Down Expand Up @@ -110,7 +112,7 @@ func doSelfUpdate(curver string) error {
func SelfUpdate(c *k8s.Client) error {
var ver = GitSummary
fmt.Printf("current karmor version %s\n", ver)
if !isValidVersion(ver) {
if !IsValidVersion(ver) {
fmt.Println("version does not match the pattern. Maybe using a locally built karmor!")
if !ConfirmUserAction("Do you want to update it?") {
return nil
Expand Down
95 changes: 94 additions & 1 deletion version/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ import (
"context"
"fmt"
"runtime"
"strings"

"github.com/blang/semver"
"github.com/fatih/color"
"github.com/google/go-github/github"
"github.com/kubearmor/kubearmor-client/k8s"
"github.com/kubearmor/kubearmor-client/selfupdate"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand All @@ -18,11 +21,17 @@ import (
// PrintVersion handler for karmor version
func PrintVersion(c *k8s.Client) error {
fmt.Printf("karmor version %s %s/%s BuildDate=%s\n", selfupdate.GitSummary, runtime.GOOS, runtime.GOARCH, selfupdate.BuildDate)
latest, latestVer := selfupdate.IsLatest(selfupdate.GitSummary)
curver := selfupdate.GitSummary
latest, latestVer := selfupdate.IsLatest(curver)
if !latest {
color.HiMagenta("update available version " + latestVer)
color.HiMagenta("use [karmor selfupdate] to update to latest")
}

mandatory, mandatoryVer := isLatestMandatory(curver)
if !mandatory {
color.HiMagenta("mandatory update available %s\n", mandatoryVer)
}
kubearmorVersion, err := getKubeArmorVersion(c)
if err != nil {
return nil
Expand All @@ -35,6 +44,90 @@ func PrintVersion(c *k8s.Client) error {
return nil
}

func isLatestMandatory(curver string) (bool, string) {
if curver != "" && !selfupdate.IsValidVersion(curver) {
return true, ""
}

latestMandatoryRelease, err := GetLatestMandatoryRelease(curver)
if err != nil {
fmt.Println("Failed to get info on mandatory release")
return true, ""
}

if latestMandatoryRelease == nil {
fmt.Println("No mandatory release found")
return true, ""
}

latestMandatory, err := semver.ParseTolerant(*latestMandatoryRelease.TagName)
if err != nil {
return true, ""
}
return false, latestMandatory.String()
}

// GetLatestMandatoryRelease finds the latest mandatory release in the given repository
// with a version greater than or equal to the given current version (in string format).
// If no such release is found, it returns an empty string and a nil error.
func GetLatestMandatoryRelease(curver string) (*github.RepositoryRelease, error) {
releases, err := FetchReleases()
if err != nil {
return nil, err
}

var latestMandatoryRelease *github.RepositoryRelease
var latestMandatoryReleaseVer *semver.Version

for _, release := range releases {
if strings.Contains(*release.Body, "mandatory") || strings.Contains(*release.Body, "MANDATORY") {
// parse the version string of the release
releaseVer, err := semver.ParseTolerant(*release.TagName)

if err != nil {
// skip the release if the version string is invalid
continue
}

// initialize the latest mandatory release version and release if they are nil
if latestMandatoryRelease == nil || latestMandatoryReleaseVer == nil {
latestMandatoryRelease = release
latestMandatoryReleaseVer = &releaseVer
continue
}

// check if the release version is greater than or equal to the current version
if curver != "" && releaseVer.GTE(semver.MustParse(curver)) && releaseVer.GT(*latestMandatoryReleaseVer) {
latestMandatoryRelease = release
latestMandatoryReleaseVer = &releaseVer
}
}
}

if latestMandatoryRelease == nil {
return nil, nil
}

return latestMandatoryRelease, nil
}

// FetchReleases fetches the list of all releases in the given repository.
func FetchReleases() ([]*github.RepositoryRelease, error) {
client := github.NewClient(nil)
releases, _, err := client.Repositories.ListReleases(context.Background(),
"kubearmor",
"kubearmor-client",
&github.ListOptions{
Page: 1,
PerPage: 100,
},
)
if err != nil {
return nil, fmt.Errorf("error fetching releases from GitHub: %v", err)
}
return releases, nil
}

func getKubeArmorVersion(c *k8s.Client) (string, error) {
pods, err := c.K8sClientset.CoreV1().Pods("kube-system").List(context.Background(), metav1.ListOptions{LabelSelector: "kubearmor-app=kubearmor"})
if err != nil {
Expand Down