puppetlabs / puppetlabs-terraform

Bolt Terraform plugin
Apache License 2.0
6 stars 18 forks source link

Proxy jump #19

Open luckyraul opened 4 years ago

luckyraul commented 4 years ago

In terraform state there is one object with a public IP, all others have privates, I guess I can use mapping to set proxyjump to a target, but how can set it from another resource? Should I parse terraform output ?

donoghuc commented 4 years ago

So the setting you want for each target's proxyjump ssh config is in a different resource? Is that static information you could set at a group level?

luckyraul commented 4 years ago
groups:
      - name: xxx_lb
        targets:
          - _plugin: terraform
            dir: ../xxx            
            resource_type: aws_instance.lb
            target_mapping:
              uri: public_ip
      - name: xxx_node
        targets:
          - _plugin: terraform
            dir: ../xxx
            resource_type: aws_instance.node
            target_mapping:
              uri: private_ip
              proxyjump: ???

I need to set jumphost from xxx_lb public_ip

donoghuc commented 4 years ago

Will the value you need for xxx_node from the aws_instance.lb resource be the same for all xxx_node targets? I'm thinking if we added functionality to just look up a single value from a resource from a statefile that would help there. So for example:

groups:
      - name: xxx_lb
        targets:
          - _plugin: terraform
            dir: ../xxx            
            resource_type: aws_instance.lb
            target_mapping:
              uri: public_ip
      - name: xxx_node
        targets:
          - _plugin: terraform
            dir: ../xxx
            resource_type: aws_instance.node
            target_mapping:
              uri: private_ip
        config:
        transport: ssh
        ssh:
           proxyjump:
             _plugin: task
             task: terraform::lookup
             dir: ../xxx
             resource: aws_instance.lb.path.to.value
luckyraul commented 4 years ago

Yes. Also I am thinking about terraform outputs. Can we use terraform outputs ?


"outputs": {
    "public_ips": {
      "value": [
        [
          "xxx.xx.x.x"
        ]
      ],
donoghuc commented 4 years ago

The output task is a good start to a generic look the value for a single resource task, but wont quite work as a plugin task because the task would need to have the data under a value key.

I'm wondering how common it will be to need a "static" value from a statefile, the exising plugin assumes you want to iterate over all the instances of a certain resource type (which breaks down if you were trying to incorporate data from another group of resources). If there are some common use cases for needing "static" values from a statefile i think we could fairly easily do that.

As far as a workaround for now, If you are willing to wrap whatever you need to do in an "inventory helper" plan you could use the xisting output task in combination with the example inventoryfile from above.. I'm thinking something roughly like:


plan inventory_helper(){
    $xxx_nodes = get_targets('xxx_node')
    $proxyjump_data = run_task('terraform::output', 'localhost', dir => 'path/to/dir')
    $xxx_nodes.each |$target| {
      $target.set_config(['ssh','proxyjump', $proxyjump_data[0].value['outputs']['public_ips']['value'][0][0]
    }
   # now $xxx_nodes should have config you need
}
luckyraul commented 4 years ago

terraform output is also in the statefile

donoghuc commented 4 years ago

I added an example that sketches out my idea for this (https://github.com/puppetlabs/puppetlabs-terraform/pull/20). I'll see what the Bolt team thinks about it this week.

(for example an inventoryfile utilizing the new task plugin might look something like the following for your case)

groups:
  - name: ssh_targets
    targets:
      _plugin: terraform
      dir: .
      resource_type: docker_container.sshd
      target_mapping:
        name: name
        config:
          ssh:
            host: ports.0.ip
            port: ports.0.external
    config:
      transport: ssh
      ssh:
        proxyjump: 
          _plugin: task
          task: terraform::tfstate_lookup
          parameters:
            dir: .
            resource_type: docker_container.sshd
            attribute_path: 0.ports.0.ip
        user: root
        password: root
        host-key-check: false
luckyraul commented 3 years ago

Will it works with facts?

donoghuc commented 3 years ago

Remember that the plugin execution operates on a "localhost" target, so the only facts that would be available are those of the bolt runner.

luckyraul commented 3 years ago

I mean, to add custom facts to a inventory group or a node from the terraform state variable

donoghuc commented 3 years ago

Yeah, plugins can be used there: for example:

targets:
  - name: foo
    facts:
      foo:
        _plugin: env_var
        var: MY_FACT
cas@cas-ThinkPad-T460p:~/working_dir/bolt$ MY_FACT=bar bolt inventory show -t foo --detail
{
  "targets": [
    {
      "name": "foo",
      "uri": null,
      "alias": [

      ],
      "config": {
        "transport": "ssh",
        "ssh": {
          "cleanup": true,
          "connect-timeout": 10,
          "disconnect-timeout": 5,
          "load-config": true,
          "login-shell": "bash",
          "tty": false,
          "host-key-check": false
        }
      },
      "vars": {
      },
      "features": [

      ],
      "facts": {
        "foo": "bar"
      },
      "plugin_hooks": {
        "puppet_library": {
          "plugin": "puppet_agent",
          "stop_service": true
        }
      },
      "groups": [
        "all"
      ]
    }
  ]
}
1 target
luckyraul commented 3 years ago

Any Updates about Release ?

h0tw1r3 commented 10 months ago

@luckyraul Yes, it works for facts like any other target map:

---
groups:
  - name: docker
    targets:
      - _plugin: terraform
        resource_type: docker_container.*
        target_mapping:
          uri: network_data.0.ip_address
          name: name
          facts:
            docker:
              id: id
              image: image
              domain: domainname
              network: network_data.0