Skip to content
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

Helm provider/allow null values #1

Merged
merged 8 commits into from
Oct 27, 2022
43 changes: 36 additions & 7 deletions provider/pkg/provider/helm_release.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ type Release struct {
ReuseValues bool `json:"reuseValues,omitempty"`
// Custom values to be merged with items loaded from values.
Values map[string]interface{} `json:"values,omitempty"`
// When combinging Values with mergeMaps, allow Nulls
AllowNullValues bool `json:"allowNullValues,omitempty"`
// If set, no CRDs will be installed. By default, CRDs are installed if not already present
SkipCrds bool `json:"skipCrds,omitempty"`
// Time in seconds to wait for any individual kubernetes operation.
Expand Down Expand Up @@ -304,7 +306,7 @@ func decodeRelease(pm resource.PropertyMap, label string) (*Release, error) {
if err = mapstructure.Decode(stripped, &release); err != nil {
return nil, fmt.Errorf("decoding failure: %w", err)
}
release.Values, err = mergeMaps(values, release.Values)
release.Values, err = mergeMaps(values, release.Values, release.AllowNullValues)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -1178,7 +1180,7 @@ func setReleaseAttributes(release *Release, r *release.Release, isPreview bool)
}
var err error
logger.V(9).Infof("Setting release values: %+v", r.Config)
release.Values, err = mergeMaps(release.Values, r.Config)
release.Values, err = mergeMaps(release.Values, r.Config, release.AllowNullValues)
if err != nil {
return err
}
Expand Down Expand Up @@ -1266,7 +1268,7 @@ func isChartInstallable(ch *helmchart.Chart) error {
func getValues(release *Release) (map[string]interface{}, error) {
var err error
base := map[string]interface{}{}
base, err = mergeMaps(base, release.Values)
base, err = mergeMaps(base, release.Values, release.AllowNullValues)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -1296,10 +1298,14 @@ func logValues(values map[string]interface{}) error {
}

// Merges a and b map, preferring values from b map
func mergeMaps(a, b map[string]interface{}) (map[string]interface{}, error) {
a = excludeNulls(a).(map[string]interface{})
b = excludeNulls(b).(map[string]interface{})

func mergeMaps(a, b map[string]interface{}, allowNullValues bool) (map[string]interface{}, error) {
if allowNullValues {
a = mapToInterface(a).(map[string]interface{})
b = mapToInterface(b).(map[string]interface{})
} else {
a = excludeNulls(a).(map[string]interface{})
b = excludeNulls(b).(map[string]interface{})
}
if err := mergo.Merge(&a, b, mergo.WithOverride, mergo.WithTypeCheck); err != nil {
return nil, err
}
Expand Down Expand Up @@ -1337,6 +1343,29 @@ func excludeNulls(in interface{}) interface{} {
return in
}

func mapToInterface(in interface{}) interface{} {
switch reflect.TypeOf(in).Kind() {
case reflect.Map:
out := map[string]interface{}{}
m := in.(map[string]interface{})
for k, v := range m {
val := reflect.ValueOf(v)
if val.IsValid() {
out[k] = mapToInterface(v)
}
}
return out
case reflect.Slice, reflect.Array:
var out []interface{}
s := in.([]interface{})
for _, i := range s {
out = append(out, mapToInterface(i))
}
return out
}
return in
}

func getChart(cpo *action.ChartPathOptions, registryClient *registry.Client, settings *cli.EnvSettings,
newRelease *Release) (*helmchart.Chart, string,
error) {
Expand Down
16 changes: 16 additions & 0 deletions sdk/python/pulumi_kubernetes/helm/v3/Release.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class ReleaseArgs:
def __init__(__self__, *,
chart: pulumi.Input[str],
atomic: Optional[pulumi.Input[bool]] = None,
allow_null_values: Optional[pulumi.Input[bool]] = False,
cleanup_on_fail: Optional[pulumi.Input[bool]] = None,
compat: Optional[pulumi.Input[str]] = None,
create_namespace: Optional[pulumi.Input[bool]] = None,
Expand Down Expand Up @@ -54,6 +55,7 @@ def __init__(__self__, *,
The set of arguments for constructing a Release resource.
:param pulumi.Input[str] chart: Chart name to be installed. A path may be used.
:param pulumi.Input[bool] atomic: If set, installation process purges chart on fail. `skipAwait` will be disabled automatically if atomic is used.
:param pulumi.Input[bool] allow_null_values: If true, allows null values in helm values when merging values
:param pulumi.Input[bool] cleanup_on_fail: Allow deletion of new resources created in this upgrade when upgrade fails.
:param pulumi.Input[bool] create_namespace: Create the namespace if it does not exist.
:param pulumi.Input[bool] dependency_update: Run helm dependency update before installing the chart.
Expand Down Expand Up @@ -89,6 +91,8 @@ def __init__(__self__, *,
pulumi.set(__self__, "chart", chart)
if atomic is not None:
pulumi.set(__self__, "atomic", atomic)
if allow_null_values is not None:
pulumi.set(__self__, "allow_null_values", allow_null_values)
if cleanup_on_fail is not None:
pulumi.set(__self__, "cleanup_on_fail", cleanup_on_fail)
if compat is not None:
Expand Down Expand Up @@ -178,6 +182,18 @@ def atomic(self) -> Optional[pulumi.Input[bool]]:
def atomic(self, value: Optional[pulumi.Input[bool]]):
pulumi.set(self, "atomic", value)

@property
@pulumi.getter
def allow_null_values(self) -> Optional[pulumi.Input[bool]]:
"""
If true, allows null values in helm values when merging values
"""
return pulumi.get(self, "allow_null_values")

@allow_null_values.setter
def allow_null_values(self, value: Optional[pulumi.Input[bool]]):
pulumi.set(self, "allow_null_values", value)

@property
@pulumi.getter(name="cleanupOnFail")
def cleanup_on_fail(self) -> Optional[pulumi.Input[bool]]:
Expand Down