code: func IsRoleVariable(variable string) (string, string, error) {
  	// time whitespace around string if it exists
  	variable = strings.TrimSpace(variable)
  
  	// strip {{ and }} from the start and end of the variable
  	if !strings.HasPrefix(variable, "{{") || !strings.HasSuffix(variable, "}}") {
  		return "", "", trace.NotFound("no variable found: %v", variable)
  	}
  	variable = variable[2 : len(variable)-2]
  
  	// parse and get the ast of the expression
  	expr, err := parser.ParseExpr(variable)
  	if err != nil {
  		return "", "", trace.NotFound("no variable found: %v", variable)
  	}
  
  	// walk the ast tree and gather the variable parts
  	variableParts, err := walk(expr)
  	if err != nil {
  		return "", "", trace.NotFound("no variable found: %v", variable)
  	}
  
  	// the variable must have two parts the prefix and the variable name itself
  	if len(variableParts) != 2 {
  		return "", "", trace.NotFound("no variable found: %v", variable)
  	}
  
  	return variableParts[0], variableParts[1], nil
  }
docs: // IsRoleVariable checks if the passed in string matches the variable pattern
  // {{external.foo}} or {{internal.bar}}. If it does, it returns the variable
  // prefix and the variable name. In the previous example this would be
  // "external" or "internal" for the variable prefix and "foo" or "bar" for the
  // variable name. If no variable pattern is found, trace.NotFound is returned.