-
Notifications
You must be signed in to change notification settings - Fork 46
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
Rehydrate last dumps by cluster #226
Merged
Merged
Changes from 21 commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
95c42e5
adding rehydrate command
jt-dd 2a0b6c9
adding list method in blob/puller
jt-dd 50c1172
grpc rehydratelatest method
jt-dd d87714f
rehydrate new proto
jt-dd 4d34244
generated grpc
jt-dd ad62e15
generated puller mock
jt-dd 4e37f39
update protobuff
jt-dd 0ba9b6a
adding DumpResult to handle all path
jt-dd 188b51d
typo logs
jt-dd 6a063f7
fixing listFiles function
jt-dd c21ba03
cleaning
jt-dd 6425339
adding unit test for the DumpResult
jt-dd a5533dd
adding unit test to IsTarGz
jt-dd ceb323e
adding unit tests for blob storage (local only)
jt-dd d245318
adding files for unit tests
jt-dd 68d175e
PR comments
jt-dd 11c216d
fix unit tests
jt-dd e438f5a
fix linter
jt-dd aac2e80
fixing unit test
jt-dd c6c1933
PR comment
jt-dd 04657f1
linter fix
jt-dd 60abdd2
merging rehydrate to ingest command
jt-dd File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
package dump | ||
|
||
import ( | ||
"fmt" | ||
"path" | ||
"regexp" | ||
) | ||
|
||
type DumpResult struct { | ||
clusterName string | ||
RunID string | ||
isDir bool | ||
extension string | ||
} | ||
|
||
const ( | ||
DumpResultClusterNameRegex = `([A-Za-z0-9\.\-_]+)` | ||
DumpResultRunIDRegex = `([a-z0-9]{26})` | ||
DumpResultExtensionRegex = `\.?([a-z0-9\.]+)?` | ||
DumpResultPrefix = "kubehound_" | ||
DumpResultFilenameRegex = DumpResultPrefix + DumpResultClusterNameRegex + "_" + DumpResultRunIDRegex + DumpResultExtensionRegex | ||
DumpResultPathRegex = DumpResultClusterNameRegex + "/" + DumpResultFilenameRegex | ||
|
||
DumpResultTarWriterExtension = "tar.gz" | ||
) | ||
|
||
func NewDumpResult(clusterName, runID string, isCompressed bool) (*DumpResult, error) { | ||
dumpResult := &DumpResult{ | ||
clusterName: clusterName, | ||
RunID: runID, | ||
isDir: true, | ||
} | ||
if isCompressed { | ||
dumpResult.Compressed() | ||
} | ||
|
||
err := dumpResult.Validate() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return dumpResult, nil | ||
} | ||
|
||
func (i *DumpResult) Validate() error { | ||
re := regexp.MustCompile(DumpResultClusterNameRegex) | ||
if !re.MatchString(i.clusterName) { | ||
return fmt.Errorf("Invalid clustername: %q", i.clusterName) | ||
} | ||
|
||
matches := re.FindStringSubmatch(i.clusterName) | ||
if len(matches) == 2 && matches[1] != i.clusterName { | ||
return fmt.Errorf("Invalid clustername: %q", i.clusterName) | ||
} | ||
|
||
re = regexp.MustCompile(DumpResultRunIDRegex) | ||
if !re.MatchString(i.RunID) { | ||
return fmt.Errorf("Invalid runID: %q", i.RunID) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (i *DumpResult) Compressed() { | ||
i.isDir = false | ||
i.extension = DumpResultTarWriterExtension | ||
} | ||
|
||
// ./<clusterName>/kubehound_<clusterName>_<run_id> | ||
func (i *DumpResult) GetFullPath() string { | ||
filename := i.GetFilename() | ||
|
||
return path.Join(i.clusterName, filename) | ||
} | ||
|
||
func (i *DumpResult) GetFilename() string { | ||
filename := fmt.Sprintf("%s%s_%s", DumpResultPrefix, i.clusterName, i.RunID) | ||
if i.isDir { | ||
return filename | ||
} | ||
|
||
return fmt.Sprintf("%s.%s", filename, i.extension) | ||
} | ||
|
||
func ParsePath(path string) (*DumpResult, error) { | ||
// ./<clusterName>/kubehound_<clusterName>_<run_id>[.tar.gz] | ||
// re := regexp.MustCompile(`([a-z0-9\.\-_]+)/kubehound_([a-z0-9\.-_]+)_([a-z0-9]{26})\.?([a-z0-9\.]+)?`) | ||
re := regexp.MustCompile(DumpResultPathRegex) | ||
if !re.MatchString(path) { | ||
return nil, fmt.Errorf("Invalid path provided: %q", path) | ||
} | ||
|
||
matches := re.FindStringSubmatch(path) | ||
// The cluster name should match (parent dir and in the filename) | ||
if matches[1] != matches[2] { | ||
return nil, fmt.Errorf("Cluster name does not match in the path provided: %q", path) | ||
} | ||
|
||
clusterName := matches[1] | ||
runID := matches[3] | ||
extension := matches[4] | ||
|
||
isCompressed := false | ||
if extension != "" { | ||
isCompressed = true | ||
} | ||
result, err := NewDumpResult(clusterName, runID, isCompressed) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return result, nil | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
UX question:
Woudn't it be better to have a flag like
--latest
or even justlatest
on theingest
subcommand?rehydrate is "another command to know" instead of "wait, I just want to ingest whatever the latest thing is but don't remember the exact path, can I just use latest and be done with 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.
yes but the ingest require the --run_id and --cluster which is not needed, so this is why I split 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.
I see, then a couple possible solution that, imo would be better, if you don't want to spend time on it, i'm fine, but that'll be harder to change later I guess :D
I think it'd be better to have:
Or, even to keep it more aligned with the current run_id flag system, just checking if
run_id==latest
would work(I think it would prefer the non flag version, because the auto completion would be simpler / expected, but that's a bit more work, so i'm find with the proposal below for now)
The current PR adds, imo, confusion about what to run and makes the feature less discover-able
kh ingest remote rehydrate # (how do you say you want to get specific cluster? e.g: If you have 500 cluster dumped, and your team manages only 4, I don't think you'll want to ingest them all?) kh ingest remote --run_id=run_xyz --cluster xyz
Rationale for the move from flags to positional arg:
--cluster
is now not mandatory (as in: it can be found by itself during "rehydrate") but--run_id
is mandatory? (as in: it's either you provide it or set for you but there's one), so it feels weird to have the two