CiscoDevNet / terraform-provider-aci

Terraform Cisco ACI provider
https://registry.terraform.io/providers/CiscoDevNet/aci/latest/docs
Mozilla Public License 2.0
88 stars 101 forks source link

aci_rest issues - Bad Request #27

Closed francesco-supportlan closed 4 years ago

francesco-supportlan commented 4 years ago

Hi,

as an example (values are just testing values), I'm trying to push the following resources:

resource "aci_rest" "terlinklevel" { path = "api/node/mo/uni/infra/hintfpol-75GBPS_FULL_INTPOL.json" class_name = "fabricHIfPol" content = { "dn" = "uni/infra/hintfpol-75GBPS_FULL_INTPOL" "name" = "75GBPS_FULL_INTPOL" "autoNeg" = "off" "speed" = "10G" "rn" = "hintfpol-75GBPS_FULL_INTPOL" } } resource "aci_rest" "terattachlinklevel2ipgpc" { path = "api/node/mo/uni/infra/funcprof/accbundle-PC_IFCE_IPG/rshIfPol.json" class_name = "infraRsHIfPol" content = { "tnFabricHIfPolName" = "75GBPS_FULL_INTPOL" } }

The 1st one (terlinklevel) is pushed an created into ACI.

The 2nd one however isn't pushed and getting a bad request. When doing a rest api call manually for the 2nd resource, here is the url and payload I have to push:

url: https://192.168.10.2/api/node/mo/uni/infra/funcprof/accbundle-PC_IFCE_IPG/rshIfPol.json payload{"infraRsHIfPol":{"attributes":{"tnFabricHIfPolName":"75GBPS_FULL_INTPOL"},"children":[]}}

When using aci_rest, I do see it's pushing a payload that results in a bad request: 2020-04-07T09:01:04.963-0400 [DEBUG] plugin.terraform-provider-aci_v0.2.0_x4: 2020/04/07 09:01:04 HTTP request after injection POST api/node/mo/uni/infra/funcprof/accbundle-PC_IFCE_IPG/rshIfPol.json &{POST https://192.168.10.2/api/node/mo/uni/infra/funcprof/accbundle-PC_IFCE_IPG/rshIfPol.json HTTP/1.1 1 1 map[Cookie:[APIC-Cookie=shgAAAAAAAAAAAAAAAAAAIn9AoH4l5+3ahXO/8Ba85+rSZTL+VKxC+aVhSMIzNvtPdj7Kb+X6wjyY9vyNOr5emPQcTh0zPY2s8G18g/QUIQTtDAWw4Jj9WwZVsLelAohrMIIy53unUvZBIBWZ/eWiHtqxkgKDADiOgUqhB2qqq6rJAaYUHEgIBeiu2s11loKUQromTGj4nLMV9QbjM05rw==]] {{"infraRsHIfPol":{"attributes":{"status":"created, modified","tnFabricHIfPolName":"75GBPS_FULL_INTPOL"}}}} 0x134de40 105 [] false 192.168.10.2 map[] map[] map[] }

2020-04-07T09:01:04.970-0400 [DEBUG] plugin.terraform-provider-aci_v0.2.0_x4: 2020/04/07 09:01:04 nHTTP Response: 400 400 Bad Request &{400 Bad Request 400 HTTP/1.1 1 1 map[Access-Control-Allow-Credentials:[false] Access-Control-Allow-Headers:[Origin, X-Requested-With, Content-Type, Accept, devcookie, APIC-challenge, Request-Tag] Access-Control-Allow-Methods:[POST,GET,OPTIONS,DELETE] Access-Control-Allow-Origin:[http://127.0.0.1:8000] Connection:[keep-alive] Content-Length:[220] Content-Type:[application/json] Date:[Tue, 07 Apr 2020 12:41:24 GMT] Server:[Cisco APIC]] 0xc000154380 220 [] false false map[] 0xc00017e000 0xc0000ba9a0}

Thanks for your help

nkatarmal-crest commented 4 years ago

@francesco-supporlan Can you please check that the interface_policy_group is created before running this terraform plan? I am able to create the relation on my end with the same code.

francesco-supportlan commented 4 years ago

Not working. When I run terraform apply it says it has created 2 resources: aci_rest.terlinklevel: Creating... aci_rest.terattachlinklevel2ipgpc: Creating... aci_rest.terlinklevel: Creation complete after 0s [id="uni/infra/hintfpol-75GBPS_FULL_INTPOL"] aci_rest.terattachlinklevel2ipgpc: Creation complete after 0s [id=uni/infra/funcprof/accbundle-PC_IFCE_IPG/rshIfPol]

Apply complete! Resources: 2 added, 0 changed, 0 destroyed.

However on ACI still not see the linklevel policy applied.

2020-04-14_09-31-21

nkatarmal-crest commented 4 years ago

@francesco-supportlan I think we are missing some required parameters for the resource. Can you double check them?

francesco-supportlan commented 4 years ago

Ok tested with only:

resource "aci_rest" "terattachlinklevel2ipgpc" { path = "api/node/mo/uni/infra/funcprof/accbundle-PC_IFCE_IPG/rshIfPol.json" class_name = "infraRsHIfPol" content = { "tnFabricHIfPolName" = "75GBPS_FULL_INTPOL" } }

Terraform Debug:

2020/04/16 08:39:00 [DEBUG] aci_rest.terattachlinklevel2ipgpc: applying the planned Create change 2020-04-16T08:39:00.642-0400 [DEBUG] plugin.terraform-provider-aci_v0.2.1_x4: 2020/04/16 08:39:00 HTTP request POST api/node/mo/uni/infra/funcprof/accbundle-PC_IFCE_IPG/rshIfPol.json &{POST https://apic2.supportlan.com/api/node/mo/uni/infra/funcprof/accbundle-PC_IFCE_IPG/rshIfPol.json HTTP/1.1 1 1 map[] {{"infraRsHIfPol":{"attributes":{"status":"created, modified","tnFabricHIfPolName":"75GBPS_FULL_INTPOL"}}}} 0x134de40 105 [] false apic2.supportlan.com map[] map[] map[] }

2020-04-16T08:39:00.711-0400 [DEBUG] plugin.terraform-provider-aci_v0.2.1_x4: HTTP Request: POST https://apic2.supportlan.com/api/node/mo/uni/infra/funcprof/accbundle-PC_IFCE_IPG/rshIfPol.json 2020-04-16T08:39:00.711-0400 [DEBUG] plugin.terraform-provider-aci_v0.2.1_x4: 2020/04/16 08:39:00 nHTTP Response: 400 400 Bad Request &{400 Bad Request 400 HTTP/1.1 1 1 map[Access-Control-Allow-Credentials:[false] Access-Control-Allow-Headers:[Origin, X-Requested-With, Content-Type, Accept, devcookie, APIC-challenge, Request-Tag] Access-Control-Allow-Methods:[POST,GET,OPTIONS,DELETE] Access-Control-Allow-Origin:[http://127.0.0.1:8000] Connection:[keep-alive] Content-Length:[220] Content-Type:[application/json] Date:[Thu, 16 Apr 2020 12:18:49 GMT] Server:[Cisco APIC]] 0xc000161440 220 [] false false map[] 0xc00013c700 0xc0003f5080} 2020-04-16T08:39:00.711-0400 [DEBUG] plugin.terraform-provider-aci_v0.2.1_x4: 2020/04/16 08:39:00

Log file: nginx.bin.log errorDetails errorCode="103" errorDescr="Cannot create Relation to Host Interface Policy (infraRsHIfPol); object uni/infra/funcprof/accbundle-PC_IFCE_IPG/rshIfPol already exists." invocationResult="unidentified-fail"

Manual API: (GET)

{ "totalCount": "1", "imdata": [ { "infraRsHIfPol": { "attributes": { "annotation": "", "childAction": "", "dn": "uni/infra/funcprof/accbundle-PC_IFCE_IPG/rshIfPol", "extMngdBy": "", "forceResolve": "yes", "lcOwn": "local", "modTs": "2020-04-14T01:03:36.989+00:00", "monPolDn": "uni/fabric/monfab-default", "rType": "mo", "state": "formed", "stateQual": "default-target", "status": "", "tCl": "fabricHIfPol", "tContextDn": "", "tDn": "uni/infra/hintfpol-default", "tRn": "hintfpol-default", "tType": "name", "tnFabricHIfPolName": "", <== Nothing is attached "uid": "0" } } } ] }

The issue is the aci_rest build the payload as: {{"infraRsHIfPol":{"attributes":{"status":"created, modified","tnFabricHIfPolName":"75GBPS_FULL_INTPOL"}}}} If you try this manually, it won't work as well as still give the same issue we see (error code 400 with text error Cannot create Relation to Host Interface Policy (infraRsHIfPol); object uni/infra/funcprof/accbundle-PC_IFCE_IPG/rshIfPol already exists). However, if you remove ["status":"created, modified",] from the payload then it works manually.

francesco-supportlan commented 4 years ago

I confirm the issue is with status value. The first time it's not attaching the relation. Then I modified the tf file and re-run an apply. Status changed to "modified" and it works.

Also do you have any examples on how to attach children attributes when we want to use aci_rest resource. (e.g.: {"infraLeafS": {"attributes": {"dn": "uni/infra/nprof-L1001_SPR/leaves-L1001_SWSEL-typ-range", "type": "range", "name": "L1001_SWSEL", "status": "created","rn": "leaves-L1001_SWSEL-typ-range"}, "children": [{"infraNodeBlk": {"attributes": {"dn": "uni/infra/nprof-L1001_SPR/leaves-L1001SWSEL-typ-range/nodeblk-1001", "from": "1001","to_": "1001", "name": "1001", "rn": "nodeblk-1001", "status": "created"},"children": []}}]}})

nkatarmal-crest commented 4 years ago

@francesco-supportlan Thanks for your investigation, I have removed the explicit status field injection in the mso_rest module. Can you please try v0.2.2 and see if it solves your issue or not?

francesco-supportlan commented 4 years ago

@nkatarmal-crest Sorry for the delay. Yes it works fine.

The aci_rest is cool but when it comes to complex body, it's not working so great. For example, when I want to build some paylod like the one below, I'm having hard time to make it work with aci_rest. Is it possible to leave content field "free" and take any dict/json as is to send it over api using aci_rest?

   if vpc is False:
        payload = '{"infraNodeP": {"attributes": {"dn": "uni/infra/nprof-' + str(sprname) + '", "name": "' + str(sprname) + '", "rn": "nprof-' + \
                  str(sprname) + '","status": "created,modified"}, "children": [{"infraLeafS": {"attributes": {"dn": "uni/infra/nprof-' + str(sprname) + '/leaves-' + str(leafname) + '_SWSEL-typ-range", "type": "range", ' \
                  '"name": "' + str(leafname) + '_SWSEL", "status": "created","rn": "leaves-' + str(leafname) + '_SWSEL-typ-range"}, ' \
                  '"children": [{"infraNodeBlk": {"attributes": {"dn": "uni/infra/nprof-' + str(sprname) + '/leaves-' + str(leafname) + '_SWSEL-typ-range/nodeblk-' + str(leafnumber) + '", ' \
                  '"from_": "' + str(leafnumber) + '","to_": "' + str(leafnumber) + '", "name": "' + str(leafnumber) + '", ' \
                  '"rn": "nodeblk-' + str(leafnumber) + '", "status": "created"},"children": [] } } ] } } ] } }'
    elif vpc is True:
        leafnumbervpc = str(int(leafnumber) + 1)
        leafblockname = str(leafnumber) + str(leafnumbervpc)
        payload = '{"infraNodeP": {"attributes": {"dn": "uni/infra/nprof-' + str(sprname) + '", "name": "' + str(sprname) + '", "rn": "nprof-' + \
                  str(sprname) + '","status": "created,modified"}, "children": [{"infraLeafS": {"attributes": {"dn": "uni/infra/nprof-' + str(sprname) + '/leaves-' + str(
            leafname) + '_SWSEL-typ-range", "type": "range", ' \
                        '"name": "' + str(leafname) + '_SWSEL", "status": "created","rn": "leaves-' + str(
            leafname) + '_SWSEL-typ-range"}, ' \
                        '"children": [{"infraNodeBlk": {"attributes": {"dn": "uni/infra/nprof-' + str(
            sprname) + '/leaves-' + str(leafname) + '_SWSEL-typ-range/nodeblk-' + str(leafblockname) + '", ' \
                                                                                                    '"from_": "' + str(
            leafnumber) + '","to_": "' + str(leafnumbervpc) + '", "name": "' + str(leafblockname) + '", ' \
                                                                                              '"rn": "nodeblk-' + str(
            leafblockname) + '", "status": "created"},"children": [] } } ] } } ] } }'

Also, is it possible to get the aci_rest working with certificate authentication?

vfiftyfive commented 4 years ago

Hi,

You can eventually create aci_rest resources in a separate TF file as a jinja template with your embedded logic defined there . You can then render your jinja template with the desired content. We'll also evaluate the idea of a json file input for the content. Regarding your question on certificates authentication for aci_rest, it uses the default provider authentications method, and you can use certificate there.

Nic

francesco-supportlan commented 4 years ago

@vfiftyfive this is exactly what I did but when your payload content has sub dictionary, it doesn't work well. When using certificate authentication on provider file, aci_rest returns authentication failed whereas the rest works well.

nkatarmal-crest commented 4 years ago

@francesco-supportlan aci_rest works perfect with the certificate based authentication as well. You just need to add a / before the word api in the path, if you are receiving bad signature error.

regarding the freestyle json body in the case i can add a new parameter to the aci_rest resource which will accept a json string as argument and will pass that to the APIC.

CC: @vfiftyfive

francesco-supportlan commented 4 years ago

ok I'm going to test it, not focused too much on certificate with aci_rest yet. Regarding the payload I pasted before, do you have an example how aci_rest would need to be configured (let's forget about variables because I use several jinja2 templates). Just to have a look how to configure aci_rest with nested dict, I'm surely missing something there.

nkatarmal-crest commented 4 years ago

@francesco-supportlan Please have a look at the new params added to support the nested dicts more easily with ACI rest.

Doc: https://www.terraform.io/docs/providers/aci/r/rest.html

francesco-supportlan commented 4 years ago

@francesco-supportlan Please have a look at the new params added to support the nested dicts more easily with ACI rest.

Doc: https://www.terraform.io/docs/providers/aci/r/rest.html

Works great! Thanks