jsonnet icon indicating copy to clipboard operation
jsonnet copied to clipboard

Generalize `in` operator to work on strings and arrays

Open sbarzowski opened this issue 7 years ago • 5 comments

In Python in operator can be used to check if a value is an element of an array or if a string is a substring of another string. It's handy, the syntax is elegant and actually I was a bit surprised it doesn't work this way already.

@sparkprime Is there a specific reason for current behavior?

@camh- @chancez

sbarzowski avatar May 08 '18 23:05 sbarzowski

yes there is a specific reason: laziness

sparkprime avatar May 09 '18 01:05 sparkprime

That's an ambiguous response. I spent a whole 30 seconds trying to figure out how lazy evaluation would be impacted by this feature and I couldn't. Then I realised you were not referring to lazy evaluation, but human laziness.

camh- avatar May 09 '18 01:05 camh-

Apologies, I was tired :)

Indeed it has nothing to do with lazy execution.

sparkprime avatar May 09 '18 15:05 sparkprime

Hello there, is there any workaround to the lack of this support?

I'm trying to run a script that contains this snippet, but it fails since I can't check if an array contains a certain string with in:

local criticalAlerts = [
  'KubePodCrashLooping',
];

local warningAlerts = [
  'KubeStateMetricsListErrors',
];

local infoAlerts = [
  'Watchdog',
];

local kp =
  (import 'kube-prometheus/main.libsonnet') +
  {
    values+:: {
      common+: {
        namespace: std.extVar('namespace'),
      },
    },

    kubernetesControlPlane+: {
      prometheusRule+: {
        spec+: {
          groups: std.map(
            function(group) group {
              rules: std.map(
                function(rule) 
                  if 'alert' in rule && (rule.alert in criticalAlerts) then
                    rule { labels+: { severity: 'critical' } }
                  else if 'alert' in rule && (rule.alert in warningAlerts) then
                    rule { labels+: { severity: 'warning' } }
                  else if 'alert' in rule && (rule.alert in infoAlerts) then
                    rule { labels+: { severity: 'info' } }
                  else
                    rule,
                super.rules
              ),
            },
            super.groups
          ),
        },
      },
    },
  }
;

EDIT: In case someone is also looking for a workaround, got that going with a map:

local alertSeverityMap = {
  KubePodCrashLooping: 'critical',
  KubeStateMetricsListErrors: 'warning',
  Watchdog: 'info',
};

local kp =
  (import 'kube-prometheus/main.libsonnet') +
  {
    values+:: {
      common+: {
        namespace: std.extVar('namespace'),
      },
    },

    kubernetesControlPlane+: {
      prometheusRule+: {
        spec+: {
          groups: std.map(
            function(group) group {
              rules: std.map(
                function(rule)
                  if 'alert' in rule && (rule.alert in alertSeverityMap) then
                    rule { labels+: { severity: alertSeverityMap[rule.alert] } }
                  else
                    rule,
                super.rules
              ),
            },
            super.groups
          ),
        },
      },
    },
  };

ArthurSens avatar Apr 13 '21 18:04 ArthurSens

A more direct way is to use std.findSubstr for strings and std.member for checking array membership. We already have the functions we need. This is just about more obvious / direct syntax.

sbarzowski avatar Apr 15 '21 19:04 sbarzowski