Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug: json output of nested optional and computed blocks differ #65

Closed
mavogel opened this issue Jan 22, 2023 · 1 comment
Closed

bug: json output of nested optional and computed blocks differ #65

mavogel opened this issue Jan 22, 2023 · 1 comment

Comments

@mavogel
Copy link

mavogel commented Jan 22, 2023

When the surrounding block is computed: true the json output of the nested attributes differs if the block would be Optional: True, whereas it should be the same.

Steps to reproduce

Create the local test directories as described in the contribution guidelines of the docker provider

  1. Clone the repo
git clone --depth 1 --branch v3.0.1 git@github.com:kreuzwerker/terraform-provider-docker.git
cd terraform-provider-docker
  1. Now in the internal/provider/resource_docker_container.go file adapt the line
"network_data": {
                                Type:        schema.TypeList,
				Description: "The data of the networks the container is connected to.",
				Optional:    true, // <- change this line. Was 'Computed:    true' before
  1. Create the test infra
# we are in the root of the terraform-provider-docker directory
# create the testing folder
mkdir testing

export TESTING_MIRROR=testing-mirror/registry.terraform.io/kreuzwerker/docker/9.9.9/$(go env GOHOSTOS)_$(go env GOHOSTARCH)
mkdir -p ./$TESTING_MIRROR
go build -o ./$TESTING_MIRROR/terraform-provider-docker_v9.9.9
  1. create testing/main.tf with the following content
Click me
terraform {
  required_providers {
    # We recommend pinning to the specific version of the Docker Provider you're using
    # since new versions are released frequently
    docker = {
      source  = "kreuzwerker/docker"
      version = "3.0.1"
      /* version = "9.9.9" */
    }
  }
}

provider "docker" {
}

# -> docker pull nginx:latest
resource "docker_image" "nginx" {
  name         = "nginx:latest"
  keep_locally = true
}

# Create a docker container resource
# -> same as 'docker run --name nginx -p8080:80 -d nginx:latest'
resource "docker_container" "nginx" {
  name    = "nginx"
  image   = docker_image.nginx.image_id

  ports {
    external = 8080
    internal = 80
  }
}
  1. Export the json schema
cd testing
terraform init
terraform providers schema -json > schema-network_data-computed.json

grep "network_data" -A 19 schema-network_data-computed.json

will give you

                            "network_data": {
                                "type": [
                                    "list",
                                    [
                                        "object",
                                        {
                                            "gateway": "string",
                                            "global_ipv6_address": "string",
                                            "global_ipv6_prefix_length": "number",
                                            "ip_address": "string",
                                            "ip_prefix_length": "number",
                                            "ipv6_gateway": "string",
                                            "network_name": "string"
                                        }
                                    ]
                                ],
                                "description": "The data of the networks the container is connected to.",
                                "description_kind": "markdown",
                                "computed": true
                            },
  1. Now change in testing/main.tf to the adapted version
terraform {
  required_providers {
    # We recommend pinning to the specific version of the Docker Provider you're using
    # since new versions are released frequently
    docker = {
      source  = "kreuzwerker/docker"
      /* version = "3.0.1" */
      version = "9.9.9" // <- here
    }
  }
}
  1. Re-initialize the provider
# we are still in the 'testing' folder
terraform init -plugin-dir=../testing-mirror -upgrade
terraform providers schema -json > schema-network_data-optional.json

grep "network_data" -A 50 schema-network_data-optional.json

will give you

                            "network_data": {
                                "nesting_mode": "list",
                                "block": {
                                    "attributes": {
                                        "gateway": {
                                            "type": "string",
                                            "description": "The network gateway of the container.",
                                            "description_kind": "markdown",
                                            "computed": true
                                        },
                                        "global_ipv6_address": {
                                            "type": "string",
                                            "description": "The IPV6 address of the container.",
                                            "description_kind": "markdown",
                                            "computed": true
                                        },
                                        "global_ipv6_prefix_length": {
                                            "type": "number",
                                            "description": "The IPV6 prefix length address of the container.",
                                            "description_kind": "markdown",
                                            "computed": true
                                        },
                                        "ip_address": {
                                            "type": "string",
                                            "description": "The IP address of the container.",
                                            "description_kind": "markdown",
                                            "computed": true
                                        },
                                        "ip_prefix_length": {
                                            "type": "number",
                                            "description": "The IP prefix length of the container.",
                                            "description_kind": "markdown",
                                            "computed": true
                                        },
                                        "ipv6_gateway": {
                                            "type": "string",
                                            "description": "The IPV6 gateway of the container.",
                                            "description_kind": "markdown",
                                            "computed": true
                                        },
                                        "network_name": {
                                            "type": "string",
                                            "description": "The name of the network",
                                            "description_kind": "markdown",
                                            "computed": true
                                        }
                                    },
                                    "description": "The data of the networks the container is connected to.",
                                    "description_kind": "markdown"
                                }
                            },

Conclusion

IMO the bug is here and not the generation of the tf-plugin-docs. See the issue: hashicorp/terraform-plugin-docs#66 as it uses the json as input

Versions

terraform version
Terraform v1.3.7
on darwin_arm64
+ provider registry.terraform.io/kreuzwerker/docker v3.0.1
@radeksimko
Copy link
Member

Hi @mavogel
I agree that this looks confusing and may be a sign of a bug somewhere. However, I don't think the bug is in terraform-json. The role of this library is merely to interpret the raw JSON into Go types and it does that correctly, given either JSON input (network_data as a block or an attribute) - i.e. it does not error/panic or ignore any data.

package main

import (
	"encoding/json"
	"io"
	"log"
	"os"

	"github.com/hashicorp/terraform-json"
	"github.com/kr/pretty"
)

func main() {
	var pSchemas tfjson.ProviderSchemas

	b, err := io.ReadAll(os.Stdin)
	if err != nil {
		log.Fatal(err)
	}

	err = json.Unmarshal(b, &pSchemas)
	if err != nil {
		log.Fatal(err)
	}

	// computed - as list(object({})) attribute
	data := pSchemas.Schemas["registry.terraform.io/kreuzwerker/docker"].ResourceSchemas["docker_container"].Block.Attributes["network_data"]

	// optional - as list block
	data := pSchemas.Schemas["registry.terraform.io/kreuzwerker/docker"].ResourceSchemas["docker_container"].Block.NestedBlocks["network_data"]

	pretty.Print(data)
}

^ feel free to pass either JSON output (as produced by terraform providers schema -json) via cat schemas.json | go run main.go

On a side note, the schemas are only dependent on configuration to the point of provider requirement (i.e. terraform -> required_providers block), all other configuration is practically ignored, i.e. the same schema is produced regardless of what else is in the configuration.

I would suggest opening this issue either in the plugin SDK repository, or TF Core.

Thanks!

@radeksimko radeksimko closed this as not planned Won't fix, can't repro, duplicate, stale Feb 3, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants