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

is it possible to add new xtr. functions using java ? #17

Closed
sandys opened this issue Jul 17, 2023 · 16 comments
Closed

is it possible to add new xtr. functions using java ? #17

sandys opened this issue Jul 17, 2023 · 16 comments

Comments

@sandys
Copy link

sandys commented Jul 17, 2023

hi
we were looking to add a few functions to xtrasonnet xtr. namespace...but wanted to do it through java. is that possible ?

@jam01
Copy link
Owner

jam01 commented Jul 17, 2023

Yes, I'll add some docs on how to do that, but here's an example that might help

https://github.com/jam01/xtrasonnet/blob/0.5.4/xtrasonnet/src/test/java/io/github/jam01/xtrasonnet/spi/LibraryTest.java

@sandys
Copy link
Author

sandys commented Jul 17, 2023

this is awesome! one followup question - ive been tracking the recent pull of sjsonnet databricks/sjsonnet#166

it theoretically allows the end developer to extend and add functions to std namespace at development time (without recompiling the sjsonnet library).
Would something like that be possible in xtrasonnet ?

@jam01
Copy link
Owner

jam01 commented Jul 17, 2023

I hadn't seen this PR. There's been some activity in sjsonnet after a long while. I'll rebase my sjsonnet fork and will release a new ver if everything's good.

@sandys
Copy link
Author

sandys commented Jul 17, 2023

appreciate it! your fork is spectacular because it adds these extra functions in here.
It would be super great if there was a provision for user defined functions as well (maybe in a different namespace "usr").

@jam01
Copy link
Owner

jam01 commented Jul 20, 2023

I'll rebase the fork, but maybe I'm not exactly following...

The library method I linked above should do what you're looking for. You can write a Java function and call it from your xtrasonnet code under any namespace you define

@sandys
Copy link
Author

sandys commented Jul 20, 2023

@jam01 thanks for looking into this. really appreciate it!

so we tried, but it keeps throwing an error. We tried to stick as close to your example as possible. is there an example that shows this ?

image
image
image

@jam01
Copy link
Owner

jam01 commented Jul 20, 2023

can you share the error stack trace?

@sandys
Copy link
Author

sandys commented Jul 20, 2023

i finally got it to work by doing this. its hacky, but was trying to fix for a few hours - so please forgive the bad code.



import com.fasterxml.jackson.databind.ObjectMapper;
import io.github.jam01.xtrasonnet.Transformer;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.RandomStringUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.*;
public abstract class JsonnetLoader {

  private final Logger logger = LoggerFactory.getLogger(this.getClass());

  private Map<String, JsonnetArgs> args = new HashMap<>();
  private Map<String, String> xtraArgsMap = new HashMap<>();
  private JSONObject jsonObject;

  public JsonnetLoader() {}

  public void load(InputStream inputStream) {
    try {
      preconfigured();

      // Create Temp File With Unique Name
      String filename =
          RandomStringUtils.randomAlphanumeric(12) + "_" + System.currentTimeMillis() + ".jsonnet";
      File file = new File(System.getProperty("java.io.tmpdir") + File.separator + filename);

      BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));

      StringBuilder sb = new StringBuilder();
      String line;
      while ((line = br.readLine()) != null) {
        sb.append(line).append(System.lineSeparator());
      }

      String text = sb.toString().replaceAll("[\r]+", "");

      PrintWriter printWriter = new PrintWriter(file);
      printWriter.write(text);
      printWriter.flush();
      printWriter.close();



      // Transform Jsonnet Args
      for (Map.Entry<String, JsonnetArgs> entry : this.args.entrySet()) {

        if (entry.getValue().getDataType().equals(DataType.STRING)) {
          String regex = "[^\\p{L}\\p{N}\\p{P}\\p{Z}]";

          xtraArgsMap.put(entry.getKey(), entry.getValue().getVal().replaceAll(regex, ""));

        } else if (entry.getValue().getDataType().equals(DataType.INTEGER)
            || entry.getValue().getDataType().equals(DataType.BOOLEAN)) {

          xtraArgsMap.put(entry.getKey(), entry.getValue().getVal());
        }
      }

      var res = Transformer.builder(text)
              .withLibrary(new XtraSonnetCustomFunc())
              .build()
              .transform(serializeXtraArgs(xtraArgsMap));

      // Get the String Output & Transform it into JsonnetSchema
      this.jsonObject = new JSONObject(res);

      // Delete File
      FileUtils.deleteQuietly(file);

    } catch (final Exception e) {
      throw new JsonnetLoaderException(e.getMessage());
    }
  }
  private static String serializeXtraArgs(Map<String, String> xtraArgsMap) {
    try {
      ObjectMapper objectMapper = new ObjectMapper();
      return objectMapper.writeValueAsString(xtraArgsMap);
    } catch (Exception e) {
      e.printStackTrace();
      return "{}";
    }
  }

  
}

@jam01
Copy link
Owner

jam01 commented Jul 20, 2023

no worries!

so did you achieve what you were looking to do?

@sandys
Copy link
Author

sandys commented Jul 20, 2023 via email

@jam01
Copy link
Owner

jam01 commented Jul 20, 2023

Ok so, xtrasonnet does not keep the ext and tla vars functionality as is. ext vars are not supported entirely and tla vars are supported as 'inputs'.

Here's an example of how inputs are used:

https://github.com/jam01/xtrasonnet/blob/0.5.4/xtrasonnet/src/test/java/io/github/jam01/xtrasonnet/NestedDocumentsTest.java

Let me know if that helps

@sandys
Copy link
Author

sandys commented Jul 25, 2023

on a longer term, what is the plan with extvars and tla vars ? will u keep them this way ? we like xtrasonnet and will probably continue to use it in the longer term, but are worried if xtrasonnet will diverge too much from the published jsonnet standard.

this is not an unusual request from me - almost every project that uses jsonnet eventually debates on tla/ext . Even in our case, we get some data from a database and inject it into the jsonnet file - so want to figure out a standard way to refer to that data. Other people will want to pass data from a UI.

e.g. argoproj/argo-cd#1107 and argoproj/argo-cd#1107 (comment)
and https://tanka.dev/jsonnet/injecting-values

@jam01
Copy link
Owner

jam01 commented Jul 25, 2023 via email

@sandys
Copy link
Author

sandys commented Jul 25, 2023

thank you - you're awesome!

@jam01
Copy link
Owner

jam01 commented Aug 4, 2023

0.6.0 has been released which uses sjsonnet 0.4.5. With this one you should be able to pass in a custom Std aside from custom xtrasonnet Library.

The aspect of tla and ext will be addressed in a different release, because there's potential backwards breaking changes.

Feel free to re-open the PR if there's something missing.

@jam01 jam01 closed this as completed Aug 4, 2023
@sandys
Copy link
Author

sandys commented Aug 5, 2023

thank you so much!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants