1

I'm using jsonnet to configure my panels in Grafana. I'm using itfor the first time and I like it a lot. However, I'm having a hard time understanding certain aspects.

I have something similar to the following:

.addTemplate(
  template.new(
    microservices,
    datasource='',
    query=std.join(',', std.map(function(x) x.text, service['microservices'])),
    label= services,
  )

What I am trying to do now is to obtain, given a microservice, the position it occupies in order to be able to assign it to the variable service (and then get my custom values whit the query=std.join(',', std.map(function(x) x.text, service['microservices'])),).

local services = std.extVar('services');
local service = services[x?];

The variable service has the following form:

[
  {
    // I'm trying to get this array position where my value is
    "key": "asd",
    "microservices": [
      {
        "key": "I HAVE THIS VALUE",
        "text": "ads"
      },
      {
        "key": "asd",
        "text": "ads"
      },
      {
        "key": "asd",
        "text": "asd"
      }
    ],
    "name": "bca",
    "services: [
      {
        "key": "bca",
        "name": "bca"
      }
    ]
  },
  {
    "key": "bca",
    "microservices": [
      {
        "key": "bca",
        "text": "bca"
      },
      {
        "key": "bca",
        "text": "bca"
      }
    ],
    "name": "bca",
    "services: [
      {
        "key": "bca",
        "name": "bca"
      }
    ]
  },
  {
    "key": "abc",
    "microservices": [
      {
        "key": "bca",
        "text": "bca"
      }
    ],
    "name": "abc",
    "services: [
      {
        "key": "ccc",
        "name": "ccc"
      }
    ]
  }
]

In any other language it seems to me a very basic operation.

var srv type
for x, service := range services{
  for _, microservice := range service.microservices{
    if microservice.key == "my value"{
      srv= services[x]
    }
}

Any tip?

Thank you so much.

Hugo L.M
  • 1,053
  • 17
  • 31

1 Answers1

3

It is also a very simple operation in Jsonnet. The most natural way to do it is with array comprehensions, which also conveniently support filtering:

local service2 = [
    s for s in services
    if [ms for ms in s.microservices if ms.key == "I HAVE THIS VALUE"] != []
][0];

Please note the indexing [0] - in general there may be more than one or none matching services in general. So if you want to get the first one, you need to take it explicitly.

The code above is written with the assumption that you don't care about the actual index, you only want to retrieve this service. If you need it, it gets a tiny bit more complicated:

local serviceIndex = [
  x for x in std.range(0, std.length(services) - 1)
  if [ms for ms in services[x].microservices if ms.key == "I HAVE THIS VALUE"] != []
][0];

BTW you could achieve the same result with functions such as std.filter, but that would be a bit more verbose.

BTW2 I would also consider extracting a function hasMicroservice(service, msKey) to enhance readability of filtering.

sbarzowski
  • 2,707
  • 1
  • 20
  • 25
  • Thank you very much @sbarzowski for the detailed explanation. It has been very useful for me to understand a little better the operation of the for loops in jsonnet. What I'm trying to do is to get that service or position (service is enought), but when it contains a certain micro service key. A service contains n micros. I want to get that service if it contains a specific microservice key (just one possibility). Or that position in the array. I'm going to try nesting loops from the code you shared with me. Thank you very much again, very kind. – Hugo L.M Nov 10 '19 at 22:23
  • 1
    @HugoL.M Oh, I missed the second level. Thanks for pointing this out. I updated the answer to include it. – sbarzowski Nov 10 '19 at 22:43