-
Notifications
You must be signed in to change notification settings - Fork 118
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
feat: Allow to collect only selected CF apps metadata through yaml; Support query depth parameter and spaceguid as filters #1026
Conversation
Thanks for making a pull request! 😃 |
Codecov ReportPatch coverage:
Additional details and impacted files@@ Coverage Diff @@
## main #1026 +/- ##
==========================================
- Coverage 15.90% 14.66% -1.25%
==========================================
Files 81 86 +5
Lines 7405 8035 +630
==========================================
Hits 1178 1178
- Misses 5922 6552 +630
Partials 305 305
☔ View full report in Codecov by Sentry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we allow for a hybrid approach:
- By default we get all info, but provide a way to specify depth and get the level of info we need.
- Also, we can allow users to filter based on space, org, etc..
- if users specify a list of apps we get the info for them, which could be in the similar format as the output of above, so that users can edit the above output and use it as input.
collector/cfappscollector.go
Outdated
|
||
// CfCollectApp defines CfCollectApp information | ||
type CfCollectApp struct { | ||
Name string `yaml:"name"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't we make name also optional. Say somebody wants to specify just the guids.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I have made name optional and the user can specify just the guids.
85029df
to
980c202
Compare
@seshapad can we review and merge this soon? |
This is the new yaml format that we support now with apiVersion: move2kube.konveyor.io/v1alpha1
kind: CfCollectApps
spec:
filters:
query_depth: "0"
spaceguid: 74faba82-c6db-40af-9179-4f4c288efdde
applications:
- application:
# guid: b3ed607d-17df-4b74-a4b3-ddb88d7d1965
name: inventory
- application:
# name: gateway
guid: 445b24f7-0877-4447-ab01-e96af6741a91
- application:
name: cfnodejsapp
guid: b48f67fb-f046-4700-bd65-e43170d802aa This would collect the metadata of apiVersion: move2kube.konveyor.io/v1alpha1
kind: CfCollectApps
spec:
filters:
spaceguid: 74faba82-c6db-40af-9179-4f4c288efdde The above yaml can be used to fetch all apps from the given spaceguid. apiVersion: move2kube.konveyor.io/v1alpha1
kind: CfCollectApps
spec:
filters:
query_depth: "1" With the above yaml, (1 & 2) It allows to filter based on query depth and spaceguid. |
|
||
// CfCollectFilters stores the spaceguid and querydepth to be used to filter while collecting metadata | ||
type CfCollectFilters struct { | ||
SpaceGuid string `yaml:"spaceguid,omitempty"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is spaceguid used in filter? What is the difference between guid and spaceguid?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A guid is for an app, and there can be multiple apps deployed to a CF space, and a CF org can contain multiple spaces which will have different spaceguids. So, we also want to support filtering apps based on spaceguid to narrow down the search results.
https://docs.cloudfoundry.org/concepts/roles.html
A space provides users with access to a shared location for app development, deployment, and maintenance.
An org can contain multiple spaces. Every app, service, and route is scoped to a space.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not also do the same for orgs?
https://cli.cloudfoundry.org/en-US/v6/org.html
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are not using orgs as filter because we cannot fetch the app data using q
query parameter through /v2/organizations/
, whereas /v2/spaces/:spaceguid
supports fetching single/all app(s) data using query parameter (for ex: cf curl /v2/spaces/74faba82-c6db-40af-9179-4f4c288efdde/apps\?q=name%3Aorders
).
collector/cfappscollector.go
Outdated
func listAppsBySpaceGuid(client *cfclient.Client, spaceGuid string, queryDepth string, collectApps []App, numCfCollectApps int) (string, []App) { | ||
query := setQueryDepth(queryDepth) | ||
path := "" | ||
if spaceGuid != "" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we have shorter return from conditions? I.e. test for spaceGuid == ""?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes sure. Done.
collector/cfappscollector.go
Outdated
func getAppByGuid(client *cfclient.Client, guid string, queryDepth string) (App, error) { | ||
var appResource AppResource | ||
query := setQueryDepth(queryDepth) | ||
requestUrl := getRequestUrl("/v2/apps/"+guid, query) // /v2/apps/:appGuid fetches the app with given guid |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you have used listAppPaths constant? If this is used only here, could you do away with constant?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have updated the requestUrl to use the listAppsPaths
constant. We are also using the listAppPaths
in two other places too.
path = listAppsPath | ||
} | ||
appSpec := cfCollectApp.AppSpec | ||
if appSpec.Guid != "" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better to use shorter if returns. Please see previous comment on this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have update the code. First we check if app Guid is given, if the app data is collected successfully for the app Guid, then we continue
the for loop for the next app. Otherwise, we check if app Name is given and try to collect the data of the app.
Also, I have made changes in the code to use shorter return in some other places too.
collector/cfappscollector.go
Outdated
func setQueryDepth(queryDepth string) url.Values { | ||
query := url.Values{} | ||
if queryDepth != "" { | ||
query.Set(inlineDepthRelations, queryDepth) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it not have been better to have a single if block to assign depth (initialized to default from global depth value) query_depth if not empty?
The set function could have used this resultant depth value.
Do you see a need for a if-else block with two different invocations of set function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes sure. Done.
…meter as variable Signed-off-by: Akash Nayak <akash19nayak@gmail.com>
…th parameter as variable Signed-off-by: Akash Nayak <akash19nayak@gmail.com>
…ry depth and space guid filters Signed-off-by: Akash Nayak <akash19nayak@gmail.com>
…ort query depth and space guid filters Signed-off-by: Akash Nayak <akash19nayak@gmail.com>
…nd support query depth and space guid filters Signed-off-by: Akash Nayak <akash19nayak@gmail.com>
77f11bd
to
8d09039
Compare
…adata and support query depth and space guid filters Signed-off-by: Akash Nayak <akash19nayak@gmail.com>
collector/cfappscollector.go
Outdated
return mergeAppResource(client, appResource), nil | ||
} | ||
|
||
func getAppsByNameOrGuid(client *cfclient.Client, path string, query url.Values, collectApps []App, appName string, appGuid string) []App { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is the appName
and appGuid
used for? Is it only for error messages? Are these values already captured in the query? If so, why not remove them and print these values at the calling site of this function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have updated the function and also renamed it, and I have removed the appGuid
which is not needed now in this function. The appName
value is captured in the query but it is in form of a string like name:inventory
(query- map[inline-relations-depth:[0] q:[name:inventory]])
. The appName can be extracted using query.Get("q")[5:]
. So, please suggest if I should pass the appName
as parameter or should I use query.Get("q")[5:]
inside the function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Akash-Nayak appName is only used for error logging right? if so, better not pass it as parameter. Also, dont extract it from the query either. You could always log the appName if getAppsByNameOrGuid()
returns an error (append or wrap it with another error message with appName in it).
collector/cfutils.go
Outdated
} | ||
|
||
// stringifyMap stringifies the map values | ||
func stringifyMap(inputMap map[string]interface{}) map[string]interface{} { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Two comments here:
- This function is not just stringifying the map, isnt it? It is using the json format, right? If so, please name the function to reflect this function.
- Should the function be moved to
common utils
package? @ashokponkumar what do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it a function that is reusable and not specific to this one flow, then move it to commons.utils. else it's fine to have it here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Two comments here:
1. This function is not just stringifying the map, isnt it? It is using the json format, right? If so, please name the function to reflect this function.
- I have renamed the function.
2. Should the function be moved to `common utils` package? @ashokponkumar what do you think?
- I have moved the function to
common utils
package.
|
||
// CfCollectFilters stores the spaceguid and querydepth to be used to filter while collecting metadata | ||
type CfCollectFilters struct { | ||
SpaceGuid string `yaml:"spaceguid,omitempty"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not also do the same for orgs?
https://cli.cloudfoundry.org/en-US/v6/org.html
…pps metadata and support query depth and space guid filters Signed-off-by: Akash Nayak <akash19nayak@gmail.com>
Signed-off-by: Akash Nayak <akash19nayak@gmail.com>
Currently
move2kube collect
fetches the metadata of all the apps that are running on Cloud Foundry instance. With this PR, we provide the user the flexibility to collect the metadata of a single app, or multiple apps, or all the apps that is/are running on Cloud Foundry.To collect metadata of all the apps there is no change required while running
move2kube collect
.$ move2kube collect -a cf
If the user wants to collect metadata of only specific application(s), then the user needs to create a simple yaml file and provide Move2Kube the path of the folder containing this yaml file while running the collect phase.
$ move2kube collect -a cf -s cfcollect
Here is a sample
cf_target_apps.yaml
file. Currently, it is optional to includeguid
,spaceguid
, andorganizationguid
.Also, I have introduced
depth
constant that can be changed when required, to change theinline-relations-depth
query parameter.Signed-off-by: Akash Nayak akash19nayak@gmail.com