-
Notifications
You must be signed in to change notification settings - Fork 105
refactor 🔨 : implement client factory for DNS client [#155] #156
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
refactor 🔨 : implement client factory for DNS client [#155] #156
Conversation
Signed-off-by: Sudipto Baral <sudiptobaral.me@gmail.com>
Signed-off-by: Sudipto Baral <sudiptobaral.me@gmail.com>
Signed-off-by: Sudipto Baral <sudiptobaral.me@gmail.com>
| credentials) | ||
| project_result['managed_zones'] = crawl.get_managed_zones( | ||
| project_id, | ||
| ClientFactory.get_client('dns').get_service(credentials), |
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.
Eventually I'd like to move each of these resource-specific client creation calls behind a function that takes the resource string (e.g. "dns") and creds, and leverages a dictionary mapping from resource string to service object. Then we can dynamically update the dict as we loop through the scan_config: either set the newly created object or re-use if it's already there for the resource key.
I'm open to doing this now, or revisiting after the we've implemented each of the clients. WDYT?
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.
Hi, I'm trying to gain a complete understanding of the motivation behind this approach. Is it because calling ClientFactory.get_client('dns').get_service(credentials) multiple times creates redundant objects in memory? If so I can think of an alternative approach also. 💡
For me, it would be more convenient to incorporate the above refactoring when we implement the double-loop approach. At this moment, I'm having difficulty visualizing the overall implementation, and I think it would be easier for me to grasp if I can start by implementing the simpler parts. Once I have a better understanding of those, I believe I will be able to comprehend this approach more easily 🎯
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, it helps us keep only one client in memory for each resource.
That sounds perfectly reasonable, let's revisit the idea later and introduce it as an isolated PR if we decide to do it.
| @staticmethod | ||
| @abstractmethod | ||
| def get_service(credentials: Credentials) -> discovery.Resource: | ||
| """Create a client. |
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.
Nit: let's update the description 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.
updated.
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.
This should be "Get a discovery resource for a client", not "Create a client", right?
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.
thanks, lets make it more verbose.
under-hill
left a comment
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.
Some spelling / documentation nits, and discussion about resource->client map
|
Thanks a ton! I am extremely sorry that I missed some of the basic docs and spelling. will be addressing your comments one by one as soon as possible. |
Signed-off-by: Sudipto Baral <sudiptobaral.me@gmail.com>
Signed-off-by: Sudipto Baral <sudiptobaral.me@gmail.com>
Signed-off-by: Sudipto Baral <sudiptobaral.me@gmail.com>
Signed-off-by: Sudipto Baral <sudiptobaral.me@gmail.com>
Signed-off-by: Sudipto Baral <sudiptobaral.me@gmail.com>
under-hill
left a comment
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.
More comment nits, and request to add another unit test
| An object of discovery.Resource | ||
| """ | ||
|
|
||
| raise NotImplementedError("Child class must implement create_client") |
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.
do you mean "must implement get_service" 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.
fixed 🙏
| @staticmethod | ||
| @abstractmethod | ||
| def get_service(credentials: Credentials) -> discovery.Resource: | ||
| """Create a client. |
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.
This should be "Get a discovery resource for a client", not "Create a client", right?
| credentials) | ||
| project_result['managed_zones'] = crawl.get_managed_zones( | ||
| project_id, | ||
| ClientFactory.get_client('dns').get_service(credentials), |
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, it helps us keep only one client in memory for each resource.
That sounds perfectly reasonable, let's revisit the idea later and introduce it as an isolated PR if we decide to do it.
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.
Let's add a test for calling ClientFactory.get_client() with a gibberish string argument, and ensuring that it logs an error and returns None as expected.
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.
added test. Also organized tests related to client factory in a Class, later on we can add at least one test case for each client factory here.
src/gcp_scanner/crawl.py
Outdated
| Args: | ||
| project_name: A name of a project to query info about. | ||
| credentials: An google.oauth2.credentials.Credentials object. | ||
| service: A resource object for interacting with the Compute API. |
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.
This should say "DNS API", not "Compute API" right?
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, or can we say GCP API?
src/gcp_scanner/crawl.py
Outdated
| Args: | ||
| project_id: An id of a project to query info about. | ||
| credentials: An google.oauth2.credentials.Credentials object. | ||
| service: A resource object for interacting with the Compute API. |
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.
This should say "DNS API", not "Compute API" right?
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.
updated
Description
closes #155
Changes Made
get_managed_zonesandtest_dns_policieswith DNSClientget_managed_zonesandtest_dns_policieswith new method signature.