Skip to content

Conversation

@matmerr
Copy link
Member

@matmerr matmerr commented Aug 14, 2020

Reason for Change:

Issue Fixed:

Adds a debug API to get IP addresses, options include "Available", "Allocated", and "All".

Usage example:

$ k exec -it azure-cns-z74hd -- /usr/local/bin/azure-cns -cmd get -darg All
{10.0.0.39 Allocated}
{10.0.0.40 Allocated}
{10.0.0.41 Available}
{10.0.0.42 Allocated}
{10.0.0.43 Available}
{10.0.0.44 Available}
...

$ k exec -it azure-cns-z74hd -- /usr/local/bin/azure-cns -cmd get -darg Allocated
{10.0.0.39 Allocated}
{10.0.0.40 Allocated}
{10.0.0.42 Allocated}
{10.0.0.45 Allocated}
{10.0.0.46 Allocated}
{10.0.0.48 Allocated}
{10.0.0.50 Allocated}
...

$ k exec -it azure-cns-z74hd -- /usr/local/bin/azure-cns -cmd get -darg Available
{10.0.0.41 Available}
{10.0.0.43 Available}
{10.0.0.44 Available}
{10.0.0.47 Available}
{10.0.0.49 Available}
{10.0.0.54 Available}

Requirements:

Notes:

@matmerr matmerr force-pushed the cnsdebugcli branch 2 times, most recently from 7f88710 to 569d53e Compare August 14, 2020 04:34
@codecov
Copy link

codecov bot commented Aug 14, 2020

Codecov Report

Merging #650 into master will decrease coverage by 0.18%.
The diff coverage is 18.01%.

@@            Coverage Diff             @@
##           master     #650      +/-   ##
==========================================
- Coverage   38.57%   38.38%   -0.19%     
==========================================
  Files          79       80       +1     
  Lines       10471    10577     +106     
==========================================
+ Hits         4039     4060      +21     
- Misses       5941     6019      +78     
- Partials      491      498       +7     

addrs, _ := iface.Addrs()
for _, address := range addrs {
if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() && ipnet.IP.To4() != nil {
ip = ipnet.IP

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should you break once you found one? Or are you looking for the last one that satisfies these criteria


printIPAddresses(addr)
default:
fmt.Printf("argument supplied for the get cmd, use the '%v' flag", acn.OptDebugCmdAlias)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are you trying to say "no/invalid argument supplied for the get cmd"?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, the error message reads a bit off

logger.Request(service.Name, &req, err)
if err != nil {
returnMessage = err.Error()
return

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you return here, returnMessage and statusCode won't do anything because your defer func() is below?


if clientDebugCmd != "" {
cnsclient.HandleCNSClientCommands(clientDebugCmd, clientDebugArg)
os.Exit(0)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should still return 1 when an error happened instead of always returning 0 even though this is just a debug tool

}

cnsurl := "http://" + ip.String() + ":10090"
cnsClient, _ := InitCnsClient(cnsurl)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is the second return value error?

should log it and exit 1 if an error happened

weng271190436
weng271190436 previously approved these changes Aug 28, 2020
Copy link
Contributor

@ramiro-gamarra ramiro-gamarra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few comments

return false
}

return addrSlice[i].IPAddress < addrSlice[j].IPAddress
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you only need this line, the rest of the block can be removed

releaseArg = "release"

eth0InterfaceName = "eth0"
azure0InterfaceName = "azure0"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some of these are unused, the rest can be consts

default:
return fmt.Errorf("No debug cmd supplied, options are: %v", getArg)
}
return nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you foresee commands other than get being added? maybe simpler to just

if !strings.EqualFold(cmd, getArg) {
    return fmt.Errorf("invalid cmd %q supplied, options are: %v", cmd, getArg)
}
return getCmd(cnsClient, arg)

or if more commands will be added, switching is fine, but I would still recommend to equalfold

)

var (
getArg = "get"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a better name for this would be getCmd

return nil
}

func getCmd(client *CNSClient, arg string) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this func should return an error. It seems the ultimate caller of these debug commands is logging any errors anyway, so it will trim down some lines below.

fmt.Println(err)
return
}
printIPAddresses(addr)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you could DRY up this block a bit by just building the args in each case, such as

var states []string
switch {
case strings.EqualFold(args, cns.Available): // this is just to make it simpler on the client, where Available or available will work
    states = append(states, cns.Available)
// ...
}
addr, err := client.GetIPAddressesMatchingStates(states...)
if err != nil {
    return err
}
printIPAddresses(addr)


// GetIPAddressesWithStates takes a variadic number of string parameters, to get all IP Addresses matching a number of states
// usage GetIPAddressesWithStates(cns.Available, cns.Allocated)
func (cnsClient *CNSClient) GetIPAddressesMatchingStates(StateFilter ...string) ([]cns.IPAddressState, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing about variadic funcs is that it's possible for clients to pass no args. I'm curious if the behavior then should be to just no-op.

body bytes.Buffer
)

httpc := &http.Client{}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can just use http.Post below (uses the default client) if we don't need any custom http config.

for _, podstate := range req.IPConfigStateFilter {
resp.IPAddresses = append(resp.IPAddresses, filterIPConfigsMatchingState(service.PodIPConfigState, podstate, func(ipconfig cns.IPConfigurationStatus, state string) bool {
return ipconfig.State == podstate
})...)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to append. You can directly assign the result of filtering to resp.IPAddresses. You can also extract the anonymous function out to make it a bit easier to read.

}

// filter the ipconfigs in CNS matching a state (Available, Allocated, etc.) and return in a slice
func filterIPConfigsMatchingState(toBeAdded map[string]cns.IPConfigurationStatus, state string, f func(cns.IPConfigurationStatus, string) bool) []cns.IPAddressState {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name seems odd given you are passing a func with which you could do the opposite :) and it also transforms the input. There are a few times when I miss generics and working with collections in a functional manner is one of them. Maybe a predicate function is not needed if we always want to filter based on a match? Would clean up the above too.

@matmerr
Copy link
Member Author

matmerr commented Oct 7, 2020

/azp run

@azure-pipelines
Copy link

No pipelines are associated with this pull request.

@matmerr
Copy link
Member Author

matmerr commented Oct 14, 2020

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

Copy link
Contributor

@ramiro-gamarra ramiro-gamarra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

@matmerr matmerr merged commit c2b8cae into Azure:master Nov 2, 2020
@matmerr matmerr deleted the cnsdebugcli branch November 2, 2020 17:53
matmerr added a commit that referenced this pull request Nov 11, 2020
* feat: add cns debug api and cli

* update tests

* fixed nits

* feedback

* remove merge artifacts

* rebase artifacts

* fix missing variable rename

* add support for pending release

* feedback

* connect to localhost
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants