-
Notifications
You must be signed in to change notification settings - Fork 12
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
Onyx-11974 write to file for push to file #367
Conversation
22354df
to
da22960
Compare
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.
Here are my comments so far, still have LOTS to get through.
@@ -0,0 +1,81 @@ | |||
package push_to_file |
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 see you're changing the package name (and the directory that it's in) to "push_to_file". The Effective Go guide section for package names says that, "By convention, packages are given lower case, single-word names; there should be no need for underscores or mixedCaps.".
In this case, push to file doesn't exactly fit the "single-word" form, but I'm thinking that we should stick with the all lower-case, no underscores convention.
Where this could make a difference is if/when this package is imported from another package... If we use "push-to-file" for the package name, then any references to exported functions in the package would be e.g. push_to_file.<ExportedFunctionName>
, which wouldn't match Go CamelCase convention.
} | ||
|
||
// Fetch secrets MOCK! | ||
// TODO: Should we make sure any secret id is only fetched once ? |
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.
// templateData describes the form in which data is presented to push-to-file templates | ||
type templateData struct { | ||
SecretsArray []*Secret | ||
SecretsMap map[string]*Secret |
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 we need both an array of secret pointers and a map to secret pointers?
I see the SecretsMap
is used for the secret
function. The SecretsArray
is used in some of the built-in templates, using a Go template range
command, but couldn't we use range
on a map?
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.
It looks like we do. We should discuss this but in trying to use the templates I realised that there are simple things you can't do without being able to have both a map or slice version of secrets
- A comma separated list like JSON requires
the slice
because you need to know which index you're on - To be able to refer to a secret by alias you need
a map
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 comments/questions. Still reviewing the UT test cases.
) (io.WriteCloser, error) | ||
|
||
// openFileToWriterCloser opens a file to write-to with some permissions. | ||
func openFileToWriterCloser(path string, permissions os.FileMode) (io.WriteCloser, error) { |
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 think I'm starting to understand the function naming convention that you're using. The ToWriterCloser
portion of this function name means that the function is returning an io.WriteCloser
(after opening the file). Is there any way that we can drop some of the details from the function names and have names that describe what it's doing from a higher level? If this would make things too vague, I can get used to this level of specificity now that I'm understanding your naming convention.
return err | ||
} | ||
|
||
return t.Execute(writer, templateData{ |
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.
The assumption here is that the call to Execute
will never display the SecretsMap
contents as part of error messages, right?
} | ||
|
||
// fileTemplate is only modified when | ||
// 1. fileTemplate is not set. fileTemplate takes precedence |
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.
Maybe this is just me, but I experienced a bit of cognitive dissonance when I read the comments: fileTemplate is only modified when . . . fileTemplate is not set
(i.e. how can it be modified if it's not set :) ). Maybe it could be fileTemplate is generated only when ... fileTemplate is not already defined
?
groupSecrets []*Secret, | ||
) error { | ||
spy._calls++ | ||
if spy._calls > 1 { |
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.
Is it even possible that the writerPusher
could be called more than once? Looks like this would be called as part of pushToFileWithDeps()
, and that function should only call the toWriterPusher
that is passed to it once and only once.
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 is to ensure the spy is only ever used once. I'll add a comment
// pushToWriter takes a (group's) path, template and secrets, and processes the template | ||
// to generate text content that is pushed to a writer. push-to-file wraps around this. | ||
func pushToWriter( | ||
writer io.Writer, |
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.
You'll probably hate this idea, but let me put it out there for consideration. I see this function is passed both an io.Writer
and a group template, and it seems that the reason these are required is that the <template>.Execute()
method needs a writer, and the <template>.Parse()
and <template>.Execute()
are done in the same operation.
But let's suppose we modularize by separating the template processing (parsing and execution) from the file writing. What I mean is that we can perform the <template>.Execute()
using a plain text buffer, and then perform the file write by writing that buffer to an actual opened file.
This would add an extra step (the file write), but it might:
- Simplify UT for the template processing??? (Not sure of this, though)
- Allow us to do other things in the future with the parsed/executed template content besides writing a file.
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 thought I had responded to this, apologies. I agree to separate these steps. Having Parse
take place at the time of consuming annotations would certainly allow SP to fail earlier.
f3f6692
to
c322e27
Compare
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 looks really good!
Just a few more very minor comments/questions, but otherwise I'm ready to approve.
annotationsFilePath, _ := filepath.Rel(workingdir, filepath.Join(basepath, "./annotations.txt")) | ||
fmt.Println("Generating " + annotationsFilePath) | ||
_ = ioutil.WriteFile(annotationsFilePath, []byte(annotations), 0644) | ||
} |
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, if you're doing any updates... last line of this file needs a newline.
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.
LGTM!!!
Although I think @rpothier has some minor comments left.
The push to file secret fetcher work is reconciled with the latest work on the write to file implementation. The push to file secret fetcher interface is updated to not rely on the existence of implementation details such as access tokens
The batch retrieval endpoint returns Conjur secrets using their full id <account>:variable:<variable_id>. Before this change this detail was spilling over into the rest of the code. The function to retrieve secrets should simply return secrets grouped by their input variable id.
168e04b
to
d6719a8
Compare
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.
LGTM!!!
Code Climate has analyzed commit d6719a8 and detected 0 issues on this pull request. The test coverage on the diff in this pull request is 79.6% (50% is the threshold). This pull request will bring the total coverage in the repository to 89.2% (-3.3% change). View more on Code Climate. |
What does this PR do?
What ticket does this PR close?
Resolves #[relevant GitHub issues, eg 76]
Checklists
Change log
Test coverage
Documentation
README
s) were updated in this PR, and/or there is a follow-on issue to update docs, or