-
Notifications
You must be signed in to change notification settings - Fork 640
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(manifests/helmfile): add helmfile templating engine #986
feat(manifests/helmfile): add helmfile templating engine #986
Conversation
bdc44b4
to
1ac6324
Compare
1ac6324
to
7eab89f
Compare
feat(manifests/helmfile): add tests
7eab89f
to
95ff86b
Compare
@@ -4,6 +4,7 @@ LABEL maintainer="sig-platform@spinnaker.io" | |||
ENV KUSTOMIZE_VERSION=3.8.6 | |||
ENV KUSTOMIZE4_VERSION=4.5.5 | |||
ENV PACKER_VERSION=1.8.1 | |||
ENV HELMFILE_VERSION=0.153.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.
I noticed that 0.154.0 has now appeared. I'm OK to go ahead with 0.153.1 and update in a follow-up PR.
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.
Since this PR, 0.155.0 has come out. Once this will be merged we are going to bump the version of helmfile.
@ConfigurationProperties("helmfile") | ||
@Data | ||
public class RoscoHelmfileConfigurationProperties { | ||
private String ExecutablePath = "helmfile"; |
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.
private String ExecutablePath = "helmfile"; | |
private String executablePath = "helmfile"; |
return "Failed to fetch helmfile " + description + ": " + e.getMessage(); | ||
} | ||
|
||
public String removeTestsDirectoryTemplates(String inputString) { |
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 figure out a way to reduce the duplication / share the code in HelmTemplateUtils.
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.
made a proposal for the this problem in here #986 (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.
Moved this method under an abstract class.
@@ -0,0 +1,18 @@ | |||
package com.netflix.spinnaker.rosco.manifests.helmfile; |
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.
License header, here and elsewhere.
@@ -0,0 +1,674 @@ | |||
/* | |||
* Copyright 2019 Google, LLC |
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.
* Copyright 2019 Google, LLC | |
* Copyright 2023 Grab Holdings, Inc. |
@@ -0,0 +1,26 @@ | |||
/* | |||
* Copyright 2020 Grab Holdings, Inc. |
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.
* Copyright 2020 Grab Holdings, Inc. | |
* Copyright 2023 Grab Holdings, Inc. |
import org.junit.runner.RunWith; | ||
import org.springframework.http.HttpStatus; | ||
|
||
@RunWith(JUnitPlatform.class) |
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.
No need for this line. Once it's gone, the imports can go too.
private String environment; | ||
private String namespace; | ||
|
||
List<Artifact> inputArtifacts; |
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.
Please add javadoc for each member, but especially this one.
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.
✅
return supportedTemplates.contains(type); | ||
} | ||
|
||
public Artifact bake(HelmfileBakeManifestRequest helmfileBakeManifestRequest) throws IOException { |
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 so close to HelmBakeManifestService. How can we share the code?
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 would put this code within the new package suggested here com.netflix.spinnaker.rosco.manifests.utils.helm
. 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.
Looking at the code this is a function a bit hard to reduce in an OOP. I would need to create a separate class (abstract) to share only thing function. happy to hear here any proposals.
throw new SpinnakerHttpException(fetchFailureMessage("values file", e), e); | ||
} catch (IOException | SpinnakerException e) { | ||
throw new IllegalStateException(fetchFailureMessage("values file", e), e); | ||
} |
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.
From here up, this basically dupilcates HelmTemplateUtils.buildBakeRecipe. How can we share the code?
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 are right. The HelmTemplateUtils
is spread of duplications. What about to create a common utils class for both helm
and helmfile
baker? Not sure under which package to place though. Perhaps I would have to create a new package com.netflix.spinnaker.rosco.manifests.utils.helm
. 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.
@dbyron-sf I've tried to make the HelmTemplateUtils
and HelmfileTemplateUtils
dryer reusing where I could the code. The only thing missing to reduce is https://github.com/thameezb/rosco/blob/7e1f5160aaa7459b22009484ea56c8b6dcd8aea9/rosco-manifests/src/main/java/com/netflix/spinnaker/rosco/manifests/helmfile/HelmfileTemplateUtils.java#L55-L97 but I cannot find a good way to reduce everything when there are in the middle POJOs. do you have any better ideas?
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've also reduce another bit the code in this commit 256756c
Signed-off-by: Salvatore Mazzarino <salvatoremazz@double.cloud>
Signed-off-by: Salvatore Mazzarino <salvatoremazz@double.cloud>
Signed-off-by: Salvatore Mazzarino <salvatoremazz@double.cloud>
Signed-off-by: Salvatore Mazzarino <salvatoremazz@double.cloud>
|
||
@ConfigurationProperties("helmfile") | ||
@Data | ||
public class RoscoHelmfileConfigurationProperties { |
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.
Prefix Rosco
is unnecessary
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.
All the other files have the Rosco
prefix. we have just used the same conventions as the other files.
|
||
import java.io.IOException; | ||
import java.nio.file.Path; | ||
import java.util.*; |
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 should avoid *
BakeRecipe result = new BakeRecipe(); | ||
result.setName(request.getOutputName()); | ||
|
||
Path helmfileFilePath; | ||
List<Path> valuePaths; | ||
|
||
List<Artifact> inputArtifacts = request.getInputArtifacts(); | ||
if (inputArtifacts == null || inputArtifacts.isEmpty()) { | ||
throw new IllegalArgumentException("At least one input artifact must be provided to bake"); | ||
} | ||
|
||
log.info("helmfileFilePath: '{}'", request.getHelmfileFilePath()); | ||
Artifact helmfileTemplateArtifact = inputArtifacts.get(0); | ||
String artifactType = Optional.ofNullable(helmfileTemplateArtifact.getType()).orElse(""); | ||
if ("git/repo".equals(artifactType)) { | ||
env.downloadArtifactTarballAndExtract(super.getArtifactDownloader(), helmfileTemplateArtifact); | ||
|
||
// If there's no helmfile path specified, assume it lives in the root of | ||
// the git/repo artifact. | ||
helmfileFilePath = | ||
env.resolvePath(Optional.ofNullable(request.getHelmfileFilePath()).orElse("")); | ||
} else { | ||
try { | ||
helmfileFilePath = downloadArtifactToTmpFile(env, helmfileTemplateArtifact); | ||
} catch (SpinnakerHttpException e) { | ||
throw new SpinnakerHttpException(fetchFailureMessage("template", e), e); | ||
} catch (IOException | SpinnakerException e) { | ||
throw new IllegalStateException(fetchFailureMessage("template", e), e); | ||
} | ||
} |
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.
seems like this code is duplicated
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 is duplicated but it is not easy to reuse. Please if you can recommend any ways to reuse this code I would appreciate it. Thanks
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 should be able to extract duplication either to a utilities class or similar in -core
type projects. Possibly rewriting some of the inputs/outputs to be more "generic" on downloading to a tmp file. Note I'm PRETTY sure kustomize uses some of this same logic, so a generic "extract artifact to folder" utility that passes the resulting FS path.
I'd also argue for a chroot type setup where each one runs in isolation or you can hit some interesting concurrency issues (which we kinda already get with tmp file support.. but... I've been seeing more edge cases lately). Don't think THIS ask is doable, but moving to a "core" lib should be.
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 @jasonmcintosh to provide some ideas. I'm going to check definitely whether the "core" lib way is a doable thing. I would like to avoid to introduce heavy refactors but certainly at this point it is too early to say that. I'll get back here once I have a more concrete idea.
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 move this method(buildBakeRecipe
) to HelmBakeTemplateUtils
class and add an abstract method for the command(buildCommand
, getCommand
)?
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.
@nemesisOsorio the whole buildBakeRecipe
depends by request
POJO which differs from Helm
and Helmfile
so moving buildBakeRecipe
into HelmBakeTemplateUtils
won't solve the problem.
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.
With the last changes, everything should result in more dry and favorite reuse.
Signed-off-by: Salvatore Mazzarino <salvatoremazz@double.cloud>
Signed-off-by: Salvatore Mazzarino <salvatoremazz@double.cloud>
Signed-off-by: Salvatore Mazzarino <salvatoremazz@double.cloud>
@jasonmcintosh @nemesisOsorio @dbyron-sf Everything has been addressed. now the code should look better. |
@thanks @nemesisOsorio for approving. cc @dbyron-sf |
Signed-off-by: Salvatore Mazzarino <salvatoremazz@double.cloud>
Signed-off-by: Salvatore Mazzarino <salvatoremazz@double.cloud>
@nemesisOsorio it's all green now. do you mind to start the merge process adding the proper label? |
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.
Overall, there are things I could see being improved, but as an initial feature I like this. Some cleanup and code reuse which is nice, overall, a solid new addition. I'd love to see the build command to be... redone but that can be a later thing.
Big thanks to @mazzy89 and @jasonmcintosh for getting this to the finish line 🚀 |
Related to spinnaker/spinnaker#6837
Adds in support for helmfile as a "Render Engine" in the "Bake (Manifest)" stage.
This allows for existing helm configuration to still be used even when using
helmfile
(including additional value artifacts and explicit overrides) - fully debatable if this functionality should be allowed or notAllows for usage with either helm2 or helm3 as the underlying templating engine - once again this is debatable if actually required
TODO: