Thread
#kubernetes
    g

    glamorous-australia-21342

    3 months ago
    I'm building a list of kubernetes resources to make easier RBAC permissions (resource - deny, instead of resource- allow all except 1), so I've made the following function, however
    jsonObj
    isnt blank outside of the
    output.apply(...
    . What am I doing wrong? If I log it inside the
    output.apply(..
    it behaves as expected. Some kind of scope thing I am not understanding I believe.
    export function createRbacJson() {
      // Generate list of valid resources names
      const getK8sApiOutput = new local.Command("get-k8s-api-output", {
        create: `kubectl api-resources --no-headers -o wide`,
      });
    
      const output = getK8sApiOutput.stdout;
    
      //output.apply(v => console.log(v))
    
      let jsonObj: any = {}
    
      output.apply(row =>
        row.split("\n").forEach(function (row) {
          const splitRow = row.match(/"[^"]*"|\[[^\][]*]|[^\s\][]+/g)
          if (splitRow != null) {
            const resourceName = splitRow[0]
        
            // if resource has a shortname skip it
            var columnModifier = 0
            if (splitRow.length == 6) {
              columnModifier++
            }
        
            const resourceApi = splitRow[1 + columnModifier]
            const namespaced = splitRow[2 + columnModifier]
            const resourceVerbs = splitRow[4 + columnModifier]?.replace(/[\[\]']+/g,'').split(/[ ,]+/)
            const verbs: string[] = []
            resourceVerbs.forEach(verb => {
              verbs.push(verb)
            });
            
            // console.log(resourceName)
            // console.log(resourceApi)
            // console.log(verbs)
            // console.log(namespaced)
            jsonObj[resourceName] = {
              api: resourceApi,
              verbs: verbs,
              namespaced: namespaced
            }
    
          }
        })
      );
      const jsonObjOutput = pulumi.output(jsonObj)
    
      return jsonObjOutput.apply(v => console.log(v))
    }
    Output of
    createRbacJson()
    {}
    g

    gorgeous-egg-16927

    3 months ago
    An
    apply
    is a callback, so it doesn’t run at the same time as your other code; it runs when the input is ready. In this case, your code basically skips the apply block and returns the empty result immediately. You can fix this by returning the result of the
    output.apply
    directly.
    export function createRbacJson() {
      // Generate list of valid resources names
      const getK8sApiOutput = new local.Command("get-k8s-api-output", {
        create: `kubectl api-resources --no-headers -o wide`,
      });
    
      const output = getK8sApiOutput.stdout;
    
      //output.apply(v => console.log(v))
    
      let jsonObj: any = {}
    
      return output.apply(row =>
        row.split("\n").forEach(function (row) {
          const splitRow = row.match(/"[^"]*"|\[[^\][]*]|[^\s\][]+/g)
          if (splitRow != null) {
            const resourceName = splitRow[0]
        
            // if resource has a shortname skip it
            var columnModifier = 0
            if (splitRow.length == 6) {
              columnModifier++
            }
        
            const resourceApi = splitRow[1 + columnModifier]
            const namespaced = splitRow[2 + columnModifier]
            const resourceVerbs = splitRow[4 + columnModifier]?.replace(/[\[\]']+/g,'').split(/[ ,]+/)
            const verbs: string[] = []
            resourceVerbs.forEach(verb => {
              verbs.push(verb)
            });
            
            // console.log(resourceName)
            // console.log(resourceApi)
            // console.log(verbs)
            // console.log(namespaced)
            jsonObj[resourceName] = {
              api: resourceApi,
              verbs: verbs,
              namespaced: namespaced
            }
    
          }
        })
      );
    }
    g

    glamorous-australia-21342

    3 months ago
    wow awesome thanks
    trying now...
    do i need an apply to get jsonObj Out? that's what i wish to return from this function
    g

    gorgeous-egg-16927

    3 months ago
    I think you could initialize it inside the apply and it would work like you want.
    g

    glamorous-australia-21342

    3 months ago
    so I tried your return method, but it outputs an Output<t>
    so then I tried this...
    console.log(createRbacJson().apply(v => v))
    and its still an Output<t>
    oh initialize the var to {}
    how do you mean?
    g

    gorgeous-egg-16927

    3 months ago
    Oh, your apply isn’t returning anything. You will need to return
    jsonObj
    from that.
    g

    glamorous-australia-21342

    3 months ago
    how? sorry
    g

    gorgeous-egg-16927

    3 months ago
    Something like this:
    output.apply(row => {
        row.split("\n").forEach(function (row) {
          const splitRow = row.match(/"[^"]*"|\[[^\][]*]|[^\s\][]+/g)
          if (splitRow != null) {
            const resourceName = splitRow[0]
        
            // if resource has a shortname skip it
            var columnModifier = 0
            if (splitRow.length == 6) {
              columnModifier++
            }
        
            const resourceApi = splitRow[1 + columnModifier]
            const namespaced = splitRow[2 + columnModifier]
            const resourceVerbs = splitRow[4 + columnModifier]?.replace(/[\[\]']+/g,'').split(/[ ,]+/)
            const verbs: string[] = []
            resourceVerbs.forEach(verb => {
              verbs.push(verb)
            });
            
            // console.log(resourceName)
            // console.log(resourceApi)
            // console.log(verbs)
            // console.log(namespaced)
            return jsonObj[resourceName] = {
              api: resourceApi,
              verbs: verbs,
              namespaced: namespaced
            }
    
          }
        })
      });
    g

    glamorous-australia-21342

    3 months ago
    oh right
    i see
    g

    gorgeous-egg-16927

    3 months ago
    Note the brackets around the function.
    apply(input => { return value })
    g

    glamorous-australia-21342

    3 months ago
    oh yes i missed those
    hmm but on the function call i get an
    .apply
    does not exit for type
    void
    g

    gorgeous-egg-16927

    3 months ago
    Since you added an explicit return, you also need to handle the
    else
    case
    g

    glamorous-australia-21342

    3 months ago
    i switched function return type to
    :any
    and
    console.log(createRbacJson().apply((v: any) => v))
    nevermind
    i dont want it to return jsonObj until the forEach is done
    i think this is returning on every iteration of the forEach
    i dont want to do anything if the row is null
    i think i need it here?
    output.apply(row => {
        row.split("\n").forEach(function (row) {
          const splitRow = row.match(/"[^"]*"|\[[^\][]*]|[^\s\][]+/g)
          if (splitRow != null) {
            const resourceName = splitRow[0]
        
            // if resource has a shortname skip it
            var columnModifier = 0
            if (splitRow.length == 6) {
              columnModifier++
            }
        
            const resourceApi = splitRow[1 + columnModifier]
            const namespaced = splitRow[2 + columnModifier]
            const resourceVerbs = splitRow[4 + columnModifier]?.replace(/[\[\]']+/g,'').split(/[ ,]+/)
            const verbs: string[] = []
            resourceVerbs.forEach(verb => {
              verbs.push(verb)
            });
            
            // console.log(resourceName)
            // console.log(resourceApi)
            // console.log(verbs)
            // console.log(namespaced)
            jsonObj[resourceName] = {
              api: resourceApi,
              verbs: verbs,
              namespaced: namespaced
            }
          }
        })
        return jsonObj
      });
    inside the new apply brackets
    const jsonObjOutput = pulumi.output(createRbacJson())
    console.log(jsonObjOutput.apply(v => v))
    dang still printing as an output
    OutputImpl {
          __pulumiOutput: true,
          resources: [Function (anonymous)],
          allResources: [Function (anonymous)],
          isKnown: Promise { <pending> },
          isSecret: Promise { <pending> },
          promise: [Function (anonymous)],
          toString: [Function (anonymous)],
          toJSON: [Function (anonymous)]
        }
    b

    billowy-army-68599

    3 months ago
    you need to print the output inside the apply
    g

    glamorous-australia-21342

    3 months ago
    right right
    i just noticed haha
    thanks!
    TypeError: Cannot read properties of undefined (reading 'apply')
    
    createRbacJson().apply((v: any) => console.log(v))
    b

    billowy-army-68599

    3 months ago
    no, it needs to be sometjing liike:
    jsonObjOutput.apply(v => console.log(v))
    g

    glamorous-australia-21342

    3 months ago
    undefined
    
    const jsonObjOutput = pulumi.output(createRbacJson())
    jsonObjOutput.apply(v => console.log(v))
    @billowy-army-68599 @gorgeous-egg-16927
    b

    billowy-army-68599

    3 months ago
    if its undefined the apply isn't returning anything, you'l need to do some more debugging
    g

    glamorous-australia-21342

    3 months ago
    if i replace the return with a console.log(jsonobj) it prints out fine which is interesting
    but then if i do console.log(createRbacJson()) its undefined
    export function createRbacJson(): any {
      // Generate list of valid resources names
      const getK8sApiOutput = new local.Command("get-k8s-api-output", {
        create: `kubectl api-resources --no-headers -o wide`,
      });
    
      const output = getK8sApiOutput.stdout;
    
      //output.apply(v => console.log(v))
    
      let jsonObj: any = {}
      output.apply(row => {
        row.split("\n").forEach(function (row) {
          const splitRow = row.match(/"[^"]*"|\[[^\][]*]|[^\s\][]+/g)
    ...
    ...
            jsonObj[resourceName] = {
              api: resourceApi,
              verbs: verbs,
              namespaced: namespaced
            }
          }
        })
      console.log(jsonObj)  
      });
    }
    Output
    ...
    ...
          securitygrouppolicies: {
            api: 'vpcresources.k8s.aws/v1beta1',
            verbs: [
              'delete',
              'deletecollection',
              'get',
              'list',
              'patch',
              'create',
              'update',
              'watch'
            ],
            namespaced: 'true'
          }
        }
    fyi all this trouble was because i didnt know
    apply
    needed a
    return
    in the function 🤦‍♂️