Skip to content

Commit

Permalink
feat: get managed cluster poc
Browse files Browse the repository at this point in the history
  • Loading branch information
bcho committed Oct 14, 2021
1 parent 97f7382 commit 9d572b4
Show file tree
Hide file tree
Showing 6 changed files with 301 additions and 7 deletions.
57 changes: 52 additions & 5 deletions aks/upgrade/demo.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import (
"fmt"
"time"

"github.com/Azure/go-autorest/autorest/azure/auth"
"github.com/Azure/go-autorest/autorest/to"
"github.com/Tatsinnit/hackathon-aks-upgrade-doctor/pkg/azure"
"github.com/Tatsinnit/hackathon-aks-upgrade-doctor/pkg/report"
"github.com/Tatsinnit/hackathon-aks-upgrade-doctor/pkg/rules"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -36,15 +39,34 @@ func (d demoRule) GetCheckResults(
func createEngineDemoCommand() *cobra.Command {
var (
flagClusterKubeConfigFilePath string
flagClusterResourceID string
)

cmd := &cobra.Command{
Use: "engine-demo",
Short: "demo for rules engine",
RunE: func(cmd *cobra.Command, args []string) error {
authorizer, err := auth.NewAuthorizerFromCLI()
if err != nil {
return fmt.Errorf("needs AZ CLI authentcation support: %w", err)
}

createClusterCtx := rules.CreateClusterContextOptions{
ClusterKubeConfigPath: flagClusterKubeConfigFilePath,
ClusterKubeConfigPath: flagClusterKubeConfigFilePath,
AzureAuthorizer: authorizer,
ManagedClusterInformation: azure.NilManagedClsuterInformation(),
}
if flagClusterResourceID != "" {
// user has specified an cluster resource id, try load cluster from it
cluster, err := azure.LoadManagedClusterInformationFromResourceID(authorizer, flagClusterResourceID)
if err != nil {
// user specified a wrong input...
return err
}
// successfully loaded the cluster
createClusterCtx.ManagedClusterInformation = cluster
}

clusterCtx, err := createClusterCtx.Create()
if err != nil {
return err
Expand All @@ -63,13 +85,32 @@ func createEngineDemoCommand() *cobra.Command {
ctx context.Context,
clusterCtx rules.ClusterContext,
) ([]*rules.CheckResult, error) {
// details := clusterCtx.GetAKSClusterResourceDetails()
cluster, err := clusterCtx.GetManagedClusterInformation(ctx)
if err != nil {
return nil, err
}

latestModel, err := cluster.GetLatestModel(ctx)
if err != nil {
return nil, err
}

category := rules.Healthy
provisionState := to.String(latestModel.ProvisioningState)
if provisionState != "Succeeded" {
category = rules.Warning
}

return []*rules.CheckResult{
{
RuleID: "upgrade/armtest",
Category: rules.Advisory,
Description: fmt.Sprintf("Got details from cluster: %s", ""),
RuleID: "upgrade/armtest",
Category: category,
Description: fmt.Sprintf(
"Got details from cluster: %s - state: %s (%s)",
cluster.GetResourceName(),
provisionState,
cluster.GetNodeResourceGroup(),
),
},
}, nil
},
Expand Down Expand Up @@ -113,6 +154,12 @@ func createEngineDemoCommand() *cobra.Command {
"",
"cluster kubeconfig to use",
)
cmd.Flags().StringVar(
&flagClusterResourceID,
"aks-resource-id",
"",
"resource id for the AKS cluster",
)

return cmd
}
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ go 1.16
require (
github.com/Azure/azure-sdk-for-go v58.2.0+incompatible
github.com/Azure/go-autorest/autorest v0.11.21
github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect
github.com/Azure/go-autorest/autorest/azure/auth v0.5.8
github.com/Azure/go-autorest/autorest/to v0.4.0
github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect
github.com/gosuri/uilive v0.0.4 // indirect
github.com/gosuri/uiprogress v0.0.1
Expand Down
15 changes: 15 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,19 @@ github.com/Azure/azure-sdk-for-go v58.2.0+incompatible h1:iCb2tuoEm3N7ZpUDOvu1Yx
github.com/Azure/azure-sdk-for-go v58.2.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest/autorest v0.11.17/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw=
github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA=
github.com/Azure/go-autorest/autorest v0.11.21 h1:w77zY/9RnUAWcIQyDC0Fc89mCvwftR8F+zsR/OH6enk=
github.com/Azure/go-autorest/autorest v0.11.21/go.mod h1:Do/yuMSW/13ayUkcVREpsMHGG+MvV81uzSCFgYPj4tM=
github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A=
github.com/Azure/go-autorest/autorest/adal v0.9.11/go.mod h1:nBKAnTomx8gDtl+3ZCJv2v0KACFHWTB2drffI1B68Pk=
github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M=
github.com/Azure/go-autorest/autorest/adal v0.9.14 h1:G8hexQdV5D4khOXrWG2YuLCFKhWYmWD8bHYaXN5ophk=
github.com/Azure/go-autorest/autorest/adal v0.9.14/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M=
github.com/Azure/go-autorest/autorest/azure/auth v0.5.8 h1:TzPg6B6fTZ0G1zBf3T54aI7p3cAT6u//TOXGPmFMOXg=
github.com/Azure/go-autorest/autorest/azure/auth v0.5.8/go.mod h1:kxyKZTSfKh8OVFWPAgOgQ/frrJgeYQJPyR5fLFmXko4=
github.com/Azure/go-autorest/autorest/azure/cli v0.4.2 h1:dMOmEJfkLKW/7JsokJqkyoYSgmR08hi9KrhjZb+JALY=
github.com/Azure/go-autorest/autorest/azure/cli v0.4.2/go.mod h1:7qkJkT+j6b+hIpzMOwPChJhTqS8VbsqqgULzMNRugoM=
github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw=
github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk=
Expand All @@ -55,6 +62,7 @@ github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+X
github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE=
github.com/Azure/go-autorest/autorest/validation v0.3.1 h1:AgyqjAd94fwNAoTjl/WQXg4VvFeRFpO+UhNyRXqF1ac=
github.com/Azure/go-autorest/autorest/validation v0.3.1/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E=
github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg=
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
Expand Down Expand Up @@ -86,6 +94,9 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U=
github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
Expand Down Expand Up @@ -251,6 +262,8 @@ github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
Expand Down Expand Up @@ -344,6 +357,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g=
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
Expand Down
29 changes: 29 additions & 0 deletions pkg/azure/client.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package azure

import (
"fmt"
"regexp"

"github.com/Azure/azure-sdk-for-go/services/containerservice/mgmt/2021-08-01/containerservice"
"github.com/Azure/go-autorest/autorest"
)
Expand All @@ -14,3 +17,29 @@ func aksManagedClusterClient(

return client
}

type ARMResourceID struct {
Subscription string
ResourceGroup string
ResourceName string
}

var regexARMResourceID = regexp.MustCompile(`(?i)^/subscriptions/(?P<subscription>[^/]*)/resourceGroups/(?P<resourceGroup>[^/]*)/providers/(?P<provider>[^/]*)/(?P<resourceType>[^/]*)/(?P<resourceName>[^/]*)$`)

// ParseARMResourceID parses a resource ID string into an ARMResourceID.
func ParseARMResourceID(id string) (*ARMResourceID, error) {
matches := regexARMResourceID.FindAllStringSubmatch(id, -1)
if len(matches) < 1 || len(matches[0]) < 5 {
return nil, fmt.Errorf("parse resource id %s: not match", id)
}

for _, m := range matches {
return &ARMResourceID{
Subscription: m[1],
ResourceGroup: m[2],
ResourceName: m[5],
}, nil
}

return nil, fmt.Errorf("parse resource id %s: not match", id)
}
167 changes: 167 additions & 0 deletions pkg/azure/managedcluster.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
package azure

import (
"context"
"fmt"
"sync"

"github.com/Azure/azure-sdk-for-go/services/containerservice/mgmt/2021-08-01/containerservice"
"github.com/Azure/go-autorest/autorest"
"github.com/Azure/go-autorest/autorest/to"
)

var ErrNotAvilable = fmt.Errorf("managed cluster resource is not available")

type nilManagedClusterInformation struct{}

var _ ManagedClusterInformation = &nilManagedClusterInformation{}

func (m *nilManagedClusterInformation) IsAvailable() bool {
return false
}

func (m *nilManagedClusterInformation) GetResourceID() string {
return ""
}

func (m *nilManagedClusterInformation) GetSubscriptionID() string {
return ""
}

func (m *nilManagedClusterInformation) GetRegion() string {
return ""
}

func (m *nilManagedClusterInformation) GetResourceGroup() string {
return ""
}

func (m *nilManagedClusterInformation) GetResourceName() string {
return ""
}

func (m *nilManagedClusterInformation) GetNodeResourceGroup() string {
return ""
}

func (m *nilManagedClusterInformation) GetLatestModel(ctx context.Context) (containerservice.ManagedCluster, error) {
return containerservice.ManagedCluster{}, ErrNotAvilable
}

func (m *nilManagedClusterInformation) GetKubeConfig(ctx context.Context) (string, error) {
return "", ErrNotAvilable
}

func (m *nilManagedClusterInformation) GetAgentPoolInformation(
ctx context.Context, agentPoolName string,
) (ManagedClusterAgentPoolInformation, error) {
return nil, ErrNotAvilable
}

type nilManagedClusterAgentPoolInformation struct{}

var _ ManagedClusterAgentPoolInformation = &nilManagedClusterAgentPoolInformation{}

func (m *nilManagedClusterAgentPoolInformation) IsAvailable() bool {
return true
}

func (m *nilManagedClusterAgentPoolInformation) GetResourceID() string {
return ""
}

func (m *nilManagedClusterAgentPoolInformation) GetSubscriptionID() string {
return ""
}

func (m *nilManagedClusterAgentPoolInformation) GetResourceGroup() string {
return ""
}

func (m *nilManagedClusterAgentPoolInformation) GetManagedClusterName() string {
return ""
}

func (m *nilManagedClusterAgentPoolInformation) GetResourceName() string {
return ""
}

func (m *nilManagedClusterAgentPoolInformation) GetLatestModel(
ctx context.Context,
) (containerservice.ManagedClusterAgentPoolProfile, error) {
return containerservice.ManagedClusterAgentPoolProfile{}, ErrNotAvilable
}

type managedClusterInfomration struct {
azureAuthorizer autorest.Authorizer

resourceID *ARMResourceID

mutex *sync.RWMutex // protects the following fields
model *containerservice.ManagedCluster
}

var _ ManagedClusterInformation = &managedClusterInfomration{}

func (m *managedClusterInfomration) IsAvailable() bool {
return true
}

func (m *managedClusterInfomration) GetResourceID() string {
m.mutex.RLock()
defer m.mutex.RUnlock()

return to.String(m.model.ID)
}

func (m *managedClusterInfomration) GetSubscriptionID() string {
return m.resourceID.Subscription
}

func (m *managedClusterInfomration) GetRegion() string {
m.mutex.RLock()
defer m.mutex.Unlock()

return to.String(m.model.Location)
}

func (m *managedClusterInfomration) GetResourceGroup() string {
return m.resourceID.ResourceGroup
}

func (m *managedClusterInfomration) GetResourceName() string {
return m.resourceID.ResourceName
}

func (m *managedClusterInfomration) GetNodeResourceGroup() string {
m.mutex.RLock()
defer m.mutex.RUnlock()

return *m.model.NodeResourceGroup
}

func (m *managedClusterInfomration) GetLatestModel(ctx context.Context) (containerservice.ManagedCluster, error) {
client := aksManagedClusterClient(m.azureAuthorizer, m.resourceID.Subscription)
managedCluster, err := client.Get(ctx, m.resourceID.ResourceGroup, m.resourceID.ResourceName)
if err != nil {
return containerservice.ManagedCluster{}, err
}

// update record
m.mutex.Lock()
m.model = &managedCluster
m.mutex.Unlock()

return managedCluster, nil
}

func (m *managedClusterInfomration) GetKubeConfig(ctx context.Context) (string, error) {
// TODO
return "", ErrNotAvilable
}

func (m *managedClusterInfomration) GetAgentPoolInformation(
ctx context.Context, agentPoolName string,
) (ManagedClusterAgentPoolInformation, error) {
return nil, ErrNotAvilable
}
Loading

0 comments on commit 9d572b4

Please sign in to comment.