How Can I Validate ConfigOption Values?

A common request from KOTS users is the ability to validate data entered in a Config field. Depending on your use case, there are a couple of options:

Option 1. Use Labels to Warn the User

Let’s say you want the user to provide an email address and would like to validate that the email is well formed. You could add a Label field that is only displayed if the email does not look right.

In the example below, a Label is displayed when the email address looks correct and another one when it does not (note that this includes the field being empty)

- name: email_addr
        title: Enter Email Address
        type: text
      - name: email_validate
        title: the email looks good
        type: label 
        when: '{{repl regexMatch "^[A-Za-z0-9._%+-][email protected][A-Za-z0-9.-]+\\.[A-Za-z]{2,}$" (ConfigOption "email_addr") }}'
      - name: email_not_validate
        title: '***Please enter a valid email address!***'
        type: label 
        when: '{{repl not (regexMatch "^[A-Za-z0-9._%+-][email protected][A-Za-z0-9.-]+\\.[A-Za-z]{2,}$" (ConfigOption "email_addr")) }}'

In the above example we are using the regexMatch sprig function to compare the value of the field against the regular expression.

To test the inverse, we used the not Go Template Function.

Here is a screenshot of the Config field containing a valid email address:

Screen Shot 2021-09-02 at 2.10.43 PM

The label then changes as soon as the email address is changed and no longer valid:

Screen Shot 2021-09-02 at 2.10.54 PM

Option 2. Use a PreFlight Check

Let’s say that during installation you want the user to provide some http address. Could be a database your app needs to connect to or some other service. Before installing your app, you want to make sure you can at least ping that address.

In this case since the validation requires an action, using labels will not work. But what we can do is create a PreFlight check to ping the address and determine if we were able to connect.

This preflight would first need a couple of Collector to get the address and then run ping against it. We’ll then need an Analyzer to see the results and display a pass/fail message to the user.

If we named our field “service_addr” the preflight would look like this:

apiVersion: troubleshoot.replicated.com/v1beta1
kind: Preflight
metadata:
  name: example-preflight-checks
spec:
  collectors:
    - run:
        collectorName: "run-ping"
        image: busybox:1
        name: ping.txt
        namespace: default
        command: ["ping"]
        args: ["-w", "10", "-c", "10", "-i", "0.3", '{{repl ConfigOption "service_addr"}}']
        imagePullPolicy: IfNotPresent
  analyzers:
    - textAnalyze:
        checkName: "Validate Address"
        fileName: ping.txt/run-ping.log
        regexGroups: '(?P<Transmitted>\d+) packets? transmitted, (?P<Received>\d+) packets? received, (?P<Loss>\d+)(\.\d+)?% packet loss'
        outcomes:
          - pass:
              when: "Loss < 5"
              message: Solid connection to {{repl ConfigOption "service_addr"}}
          - fail:
              message: Unable to establish a solid connection to {{repl ConfigOption "service_addr"}}, please ensure this is valid

There is a similar example in the docs.

Data Redaction

One note to make is that when you are using Collectors, some values will automatically be redacted. So the above example may not work if you want to validate an IP address, as that is one of the values that gets redacted

Debugging

One of the challenges debugging preflight checks is that collector results are not easily available. However, they are available if you add the collector to a SupportBundle.