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

Query VMImage version #2207

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions pkg/api/plugin.go
Expand Up @@ -146,6 +146,12 @@ type GenevaActions interface {
// GetControlPlanePods fetches a consolidated list of the control plane pods in the cluster
GetControlPlanePods(ctx context.Context, oc *OpenShiftManagedCluster) ([]byte, error)

// GetClusterLiveInfo fetches a list of the VMImage version, sync pod and webconsole of the cluster
GetImageVerInfo(ctx context.Context, oc *OpenShiftManagedCluster) (*GenevaActionGetImageVerInfo, error)

// GetClusterLiveInfo fetches a list of sync pod and webconsole version of the cluster
GetLiveClusterInfo(ctx context.Context, oc *OpenShiftManagedCluster) ([]byte, error)
gburges marked this conversation as resolved.
Show resolved Hide resolved

// ForceUpdate forces rotates all vms in a cluster
ForceUpdate(ctx context.Context, cs *OpenShiftManagedCluster, deployer DeployFn) *PluginError

Expand Down
5 changes: 5 additions & 0 deletions pkg/api/types.go
Expand Up @@ -298,3 +298,8 @@ type GenevaActionListEtcdBackups struct {
Name string `json:"name,omitempty"`
LastModified time.Time `json:"lastModified,omitempty"`
}

//GenevaActionGetClusterLiveInfo returns the VM image version used to build the nodes
type GenevaActionGetImageVerInfo struct {
ImageVer *[]string `json:"version,omitempty"`
}
21 changes: 21 additions & 0 deletions pkg/cluster/admin_actions.go
Expand Up @@ -37,6 +37,27 @@ func (u *Upgrade) ListVMHostnames(ctx context.Context) ([]string, error) {
return hostnames, nil
}

func (u *Upgrade) GetImageVerInfo(ctx context.Context) ([]string, error) {
scalesets, err := u.Ssc.List(ctx, u.Cs.Properties.AzProfile.ResourceGroup)
if err != nil {
return nil, err
}

var imagever []string
for _, ss := range scalesets {
vms, err := u.Vmc.List(ctx, u.Cs.Properties.AzProfile.ResourceGroup, *ss.Name, "", "", "")
if err != nil {
return nil, err
}

for _, vm := range vms {
imagever = append(imagever, strings.ToLower(*vm.VirtualMachineScaleSetVMProperties.StorageProfile.ImageReference.Version))
}
}

return imagever, nil
}

func (u *Upgrade) RunCommand(ctx context.Context, scaleset, instanceID, command string) error {
return u.Vmc.RunCommand(ctx, u.Cs.Properties.AzProfile.ResourceGroup, scaleset, instanceID, compute.RunCommandInput{
CommandID: to.StringPtr("RunShellScript"),
Expand Down
27 changes: 27 additions & 0 deletions pkg/cluster/kubeclient/status.go
Expand Up @@ -26,6 +26,33 @@ func (u *Kubeclientset) GetControlPlanePods(ctx context.Context) ([]v1.Pod, erro
return pods, nil
}

func (u *Kubeclientset) GetLiveClusterInfo(ctx context.Context) ([]v1.Pod, error) {
namespaces, err := u.Client.CoreV1().Namespaces().List(metav1.ListOptions{})
if err != nil {
return nil, err
}
var pods []v1.Pod
for _, namespace := range namespaces.Items {
if IsControlPlaneNamespace(namespace.Name) {
list, err := u.Client.CoreV1().Pods(namespace.Name).List(metav1.ListOptions{IncludeUninitialized: true, LabelSelector: "app=sync"})
if err != nil {
return nil, err
}
pods = append(pods, list.Items...)
}
}
for _, namespace := range namespaces.Items {
if IsControlPlaneNamespace(namespace.Name) {
list, err := u.Client.CoreV1().Pods(namespace.Name).List(metav1.ListOptions{IncludeUninitialized: true, LabelSelector: "app=openshift-web-console"})
if err != nil {
return nil, err
}
pods = append(pods, list.Items...)
}
}
return pods, nil
}

func IsControlPlaneNamespace(namespace string) bool {
if namespace == "default" || namespace == "openshift" {
return true
Expand Down
128 changes: 128 additions & 0 deletions pkg/cluster/kubeclient/status_test.go
Expand Up @@ -134,3 +134,131 @@ func TestGetControlPlanePods(t *testing.T) {
}
}
}

func TestGetLiveClusterInfo(t *testing.T) {
tests := []struct {
name string
kc kubernetes.Interface
namespaces []string
wantResult []corev1.Pod
wantErr bool
}{
{
name: "control plane namespace not found",
namespaces: []string{"test"},
wantErr: false,
kc: fake.NewSimpleClientset(),
},
{
name: "control plane namespace found, no pods found",
namespaces: []string{"kube-system"},
wantErr: false,
kc: fake.NewSimpleClientset(&corev1.Namespace{
TypeMeta: metav1.TypeMeta{
Kind: "namespace",
},
ObjectMeta: metav1.ObjectMeta{
Name: "kube-system",
},
Status: corev1.NamespaceStatus{
Phase: corev1.NamespaceActive,
},
}),
},
{
name: "control plane namespaces found, pods found",
namespaces: []string{"openshift-web-console", "test", "openshift-node"},
wantErr: false,
wantResult: []corev1.Pod{
{
TypeMeta: metav1.TypeMeta{
Kind: "pod",
},
ObjectMeta: metav1.ObjectMeta{
Name: "sync-test",
Namespace: "openshift-node",
Labels: map[string]string{"app": "sync"},
},
},
{
TypeMeta: metav1.TypeMeta{
Kind: "pod",
},
ObjectMeta: metav1.ObjectMeta{
Name: "openshift-web-console-test",
Namespace: "openshift-web-console",
Labels: map[string]string{"app": "openshift-web-console"},
},
},
},
kc: fake.NewSimpleClientset(&corev1.Namespace{
TypeMeta: metav1.TypeMeta{
Kind: "namespace",
},
ObjectMeta: metav1.ObjectMeta{
Name: "openshift-web-console",
},
Status: corev1.NamespaceStatus{
Phase: corev1.NamespaceActive,
},
}, &corev1.Namespace{
TypeMeta: metav1.TypeMeta{
Kind: "namespace",
},
ObjectMeta: metav1.ObjectMeta{
Name: "test",
},
Status: corev1.NamespaceStatus{
Phase: corev1.NamespaceActive,
},
}, &corev1.Namespace{
TypeMeta: metav1.TypeMeta{
Kind: "namespace",
},
ObjectMeta: metav1.ObjectMeta{
Name: "openshift-node",
},
Status: corev1.NamespaceStatus{
Phase: corev1.NamespaceActive,
},
}, &corev1.Pod{
TypeMeta: metav1.TypeMeta{
Kind: "pod",
},
ObjectMeta: metav1.ObjectMeta{
Name: "openshift-web-console-test",
Namespace: "openshift-web-console",
Labels: map[string]string{"app": "openshift-web-console"},
},
}, &corev1.Pod{
TypeMeta: metav1.TypeMeta{
Kind: "pod",
},
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "test",
},
}, &corev1.Pod{
TypeMeta: metav1.TypeMeta{
Kind: "pod",
},
ObjectMeta: metav1.ObjectMeta{
Name: "sync-test",
Namespace: "openshift-node",
Labels: map[string]string{"app": "sync"},
},
}),
},
}
for _, tt := range tests {
u := &Kubeclientset{Client: tt.kc}
got, err := u.GetLiveClusterInfo(context.Background())
if (err != nil) != tt.wantErr {
t.Errorf("GetControlPlanePods() error = %v, wantErr %v. Test: %v", err, tt.wantErr, tt.name)
return
}
if !reflect.DeepEqual(got, tt.wantResult) {
t.Errorf("GetControlPlanePods() = %v, want %v. Test: %v", got, tt.wantResult, tt.name)
}
}
}
3 changes: 2 additions & 1 deletion pkg/cluster/kubeclient/types.go
Expand Up @@ -15,13 +15,14 @@ import (
"k8s.io/client-go/kubernetes"
)

// Interface interface to utility kubenetes functions
// Interface interface to utility kubernetes functions
type Interface interface {
BackupCluster(ctx context.Context, backupName string) error
DrainAndDeleteWorker(ctx context.Context, hostname string) error
DeleteMaster(hostname string) error
EnsureSyncPod(ctx context.Context, syncImage string, hash []byte) error
GetControlPlanePods(ctx context.Context) ([]corev1.Pod, error)
GetLiveClusterInfo(ctx context.Context) ([]corev1.Pod, error)
WaitForReadyMaster(ctx context.Context, hostname string) error
WaitForReadyWorker(ctx context.Context, hostname string) error
WaitForReadySyncPod(ctx context.Context) error
Expand Down
1 change: 1 addition & 0 deletions pkg/cluster/types.go
Expand Up @@ -57,6 +57,7 @@ type Upgrader interface {
Restart(ctx context.Context, scaleset, instanceID string) error
Reimage(ctx context.Context, scaleset, instanceID string) error
ListVMHostnames(ctx context.Context) ([]string, error)
GetImageVerInfo(ctx context.Context) ([]string, error)
RunCommand(ctx context.Context, scaleset, instanceID, command string) error
WriteStartupBlobs() error
GenerateARM(ctx context.Context, backupBlob string, isUpdate bool, suffix string) (map[string]interface{}, error)
Expand Down
18 changes: 18 additions & 0 deletions pkg/fakerp/admin_handlers.go
Expand Up @@ -35,6 +35,24 @@ func (s *Server) handleListClusterVMs(w http.ResponseWriter, req *http.Request)
s.adminreply(w, err, vms)
}

// handleGetClusterLiveInfo handles the admin request to list the image version of the VM
func (s *Server) handleGetClusterLiveInfo(w http.ResponseWriter, req *http.Request) {
cs := req.Context().Value(contextKeyContainerService).(*api.OpenShiftManagedCluster)

imagever, err := s.plugin.GetClusterLiveInfo(req.Context(), cs)
s.adminreply(w, err, imagever)

}

// handleGetLiveClusterInfo handles the admin request to list the image version of the VM
func (s *Server) handleGetLiveClusterInfo(w http.ResponseWriter, req *http.Request) {
cs := req.Context().Value(contextKeyContainerService).(*api.OpenShiftManagedCluster)

pods, err := s.plugin.GetLiveClusterInfo(req.Context(), cs)
s.adminreply(w, err, pods)

}

// handleRestart handles restarting a vm in the cluster
func (s *Server) handleRestart(w http.ResponseWriter, req *http.Request) {
cs := req.Context().Value(contextKeyContainerService).(*api.OpenShiftManagedCluster)
Expand Down
2 changes: 2 additions & 0 deletions pkg/fakerp/routes.go
Expand Up @@ -27,6 +27,8 @@ func (s *Server) setupRoutes() {
s.router.Get(filepath.Join("/admin", s.basePath, "/status"), s.handleGetControlPlanePods)
s.router.Put(filepath.Join("/admin", s.basePath, "/forceUpdate"), s.handleForceUpdate)
s.router.Get(filepath.Join("/admin", s.basePath, "/listClusterVMs"), s.handleListClusterVMs)
s.router.Get(filepath.Join("/admin", s.basePath, "/getImageVerInfo"), s.handleGetImageVerInfo)
s.router.Get(filepath.Join("/admin", s.basePath, "/getClusterLiveInfo"), s.handleGetClusterLiveInfo)
s.router.Put(filepath.Join("/admin", s.basePath, "/restart/{hostname}"), s.handleRestart)
s.router.Put(filepath.Join("/admin", s.basePath, "/reimage/{hostname}"), s.handleReimage)
s.router.Put(filepath.Join("/admin", s.basePath, "/backup/{backupName}"), s.handleBackup)
Expand Down
30 changes: 30 additions & 0 deletions pkg/plugin/plugin.go
Expand Up @@ -574,6 +574,36 @@ func (p *plugin) ListClusterVMs(ctx context.Context, cs *api.OpenShiftManagedClu
return &api.GenevaActionListClusterVMs{VMs: &pods}, nil
}

func (p *plugin) GetLiveClusterInfo(ctx context.Context, cs *api.OpenShiftManagedCluster) ([]byte, error) {
p.log.Info("creating clients")
clusterUpgrader, err := p.upgraderFactory(ctx, p.log, cs, true, true, p.testConfig)
if err != nil {
return nil, &api.PluginError{Err: err, Step: api.PluginStepClientCreation}
}

p.log.Infof("querying control plane pods")
pods, err := clusterUpgrader.GetLiveClusterInfo(ctx)
if err != nil {
return nil, err
}
return json.Marshal(pods)
}

func (p *plugin) GetImageVerInfo(ctx context.Context, cs *api.OpenShiftManagedCluster) (*api.GenevaActionGetClusterLiveInfo, error) {
p.log.Info("creating clients")
clusterUpgrader, err := p.upgraderFactory(ctx, p.log, cs, true, true, p.testConfig)
if err != nil {
return nil, err
}

p.log.Infof("listing cluster VM image version")
imagever, err := clusterUpgrader.GetImageVerInfo(ctx)
if err != nil {
return nil, err
}
return &api.GenevaActionGetImageVerInfo{ImageVer: &imagever}, nil
}

func (p *plugin) Restart(ctx context.Context, cs *api.OpenShiftManagedCluster, hostname string) error {
if !validate.IsValidAgentPoolHostname(hostname) {
return fmt.Errorf("invalid hostname %q", hostname)
Expand Down
30 changes: 30 additions & 0 deletions pkg/util/mocks/mock_cluster/types.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions pkg/util/mocks/mock_kubeclient/types.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.