Practice Questions Overview
Test your understanding of the development setup concepts covered in this module. These questions range from basic recall to advanced application of knowledge.
Scoring Guide:
- 80-100%: Excellent! Ready to move forward
- 60-79%: Good, review specific topics
- Below 60%: Review the module before proceeding
Part 1: Multiple Choice
Question 1
What is the minimum Go version required for Terraform provider development?
A) Go 1.18
B) Go 1.19
C) Go 1.21
D) Go 1.22
View Answer
**Answer: C) Go 1.21**
Plugin Framework 1.5+ requires Go 1.21 or later for generics support and other modern Go features.
Question 2
Which command initializes a new Go module?
A) go create module
B) go mod init <module-path>
C) go init module
D) go new module <path>
View Answer
**Answer: B) `go mod init `**
This creates a new go.mod file with the specified module path.
</details>
---
### Question 3
What is the purpose of the `internal/` directory in a provider project?
A) Store internal documentation
B) House private packages that cannot be imported externally
C) Keep internal API code
D) Store provider configuration files
View Answer
**Answer: B) House private packages that cannot be imported externally**
The `internal/` directory is a Go convention that prevents external modules from importing packages within it, enforcing encapsulation.
---
### Question 4
Which file contains cryptographic checksums of module dependencies?
A) go.mod
B) go.lock
C) go.sum
D) dependencies.lock
View Answer
**Answer: C) go.sum**
go.sum contains cryptographic checksums that ensure dependency integrity and enable reproducible builds.
---
### Question 5
What is the recommended way to add a new dependency to a Go project?
A) Manually edit go.mod
B) Use `go get `
C) Use `go install `
D) Use `go download `
View Answer
**Answer: B) Use `go get `**
While manual editing works, `go get` is the recommended approach as it updates go.mod, go.sum, and downloads the package.
</details>
---
### Question 6
Which directory contains auto-generated documentation for the provider?
A) documentation/
B) docs/
C) doc/
D) manual/
View Answer
**Answer: B) docs/**
The docs/ directory contains auto-generated documentation created by terraform-plugin-docs tool.
---
### Question 7
What command removes unused dependencies and adds missing ones?
A) `go mod clean`
B) `go mod tidy`
C) `go mod prune`
D) `go mod sync`
View Answer
**Answer: B) `go mod tidy`**
go mod tidy ensures go.mod matches the imports in your code by adding missing and removing unused dependencies.
---
### Question 8
Where should provider examples be stored?
A) tests/
B) samples/
C) examples/
D) demos/
View Answer
**Answer: C) examples/**
The examples/ directory is the standard location for working Terraform configuration examples.
---
### Question 9
Which tool is used to scaffold a new Terraform provider?
A) terraform-scaffold
B) HashiCorp's provider template repository
C) provider-init
D) terraform-plugin-init
View Answer
**Answer: B) HashiCorp's provider template repository**
HashiCorp provides terraform-provider-scaffolding-framework, a GitHub template repository for creating new providers.
---
### Question 10
What is the purpose of the .goreleaser.yml file?
A) Release notes generation
B) Multi-platform build and release automation
C) Goroutine management
D) Go version release tracking
View Answer
**Answer: B) Multi-platform build and release automation**
GoReleaser automates building binaries for multiple platforms, packaging, and GitHub release creation.
---
## Part 2: Short Answer Questions
### Question 11
Explain the difference between direct and indirect dependencies in go.mod.
View Answer
**Direct dependencies** are packages that your code explicitly imports. They appear in the require block without the `// indirect` comment.
**Indirect dependencies** are packages that your direct dependencies need, but your code doesn't import directly. They're marked with `// indirect` in go.mod.
Example:
```go
require (
github.com/hashicorp/terraform-plugin-framework v1.5.0 // direct
github.com/fatih/color v1.16.0 // indirect
)
```
---
### Question 12
Why should the go.sum file be committed to version control?
View Answer
go.sum should be committed because:
1. **Reproducible builds**: Ensures everyone gets the exact same dependencies
2. **Security**: Detects tampering or corruption of dependencies
3. **Integrity**: Verifies downloaded modules match expected checksums
4. **Team consistency**: All developers use identical dependency versions
Without go.sum, builds might use different dependency versions, causing inconsistencies.
---
### Question 13
What is the purpose of the Provider Address in main.go, and what format should it follow?
View Answer
The **Provider Address** identifies where the provider is published in the Terraform Registry.
**Format:**
```
registry.terraform.io/{namespace}/{provider-name}
```
**Example:**
```go
Address: "registry.terraform.io/YOUR_USERNAME/mycloud"
```
**Purpose:**
- Uniquely identifies the provider
- Enables Terraform to locate and download it
- Required for registry publication
- Used in `required_providers` blocks
---
### Question 14
Explain Minimum Version Selection (MVS) in Go modules.
View Answer
**Minimum Version Selection (MVS)** is Go's dependency resolution algorithm.
**How it works:**
- Selects the **minimum** version that satisfies all requirements
- Does NOT automatically update to latest versions
- Ensures predictability and stability
**Example:**
```
Your code requires: v1.2.0
Dependency A requires: v1.1.0
Dependency B requires: v1.3.0
Go selects: v1.3.0
```
v1.3.0 is the minimum version that satisfies all requirements (≥ v1.1.0, ≥ v1.2.0, and ≥ v1.3.0).
**Benefits:**
- Reproducible builds
- No surprise updates
- Explicit version management
---
### Question 15
What is the difference between `pkg/` and `internal/` directories in Go projects?
View Answer
**internal/:**
- **Private packages** that cannot be imported by external modules
- Go enforces this at the compiler level
- Used for provider implementation code
- Recommended for Terraform providers
**pkg/:**
- **Public packages** that can be imported by other projects
- No compiler restrictions
- Used for shared libraries and utilities
**For providers:** Use `internal/` because provider code shouldn't be imported as a library—providers are consumed via Terraform's plugin protocol, not Go imports.
---
## Part 3: Hands-On Exercises
### Exercise 1: Dependency Investigation
Using the provider you created in the lab:
```bash
# List all dependencies
go list -m all
# Find why a specific dependency is included
go mod why github.com/hashicorp/terraform-plugin-go
# View dependency graph
go mod graph | head -20
```
**Task:** Explain the dependency chain from your provider to `terraform-plugin-go`.
View Answer
The dependency chain typically looks like:
```
your-provider
└─> terraform-plugin-framework
└─> terraform-plugin-go
```
**Explanation:**
- Your provider directly depends on Plugin Framework
- Plugin Framework depends on Plugin Go for low-level GRPC communication
- This makes Plugin Go an indirect dependency in your provider
You can verify with:
```bash
go mod why github.com/hashicorp/terraform-plugin-go
```
---
### Exercise 2: Project Structure Verification
Create a script to verify your provider follows standard structure.
View Answer
```bash
#!/bin/bash
echo "Checking provider structure..."
# Required files
required_files=(
"main.go"
"go.mod"
"go.sum"
"README.md"
"LICENSE"
".gitignore"
)
# Required directories
required_dirs=(
"internal/provider"
"examples/provider"
"docs"
)
echo ""
echo "Required Files:"
for file in "${required_files[@]}"; do
if [ -f "$file" ]; then
echo "✅ $file"
else
echo "❌ $file (missing)"
fi
done
echo ""
echo "Required Directories:"
for dir in "${required_dirs[@]}"; do
if [ -d "$dir" ]; then
echo "✅ $dir"
else
echo "❌ $dir (missing)"
fi
done
echo ""
echo "Provider binary:"
if [ -f "terraform-provider-"* ]; then
echo "✅ Found provider binary"
else
echo "⚠️ No provider binary (run 'go build')"
fi
```
Save as `check-structure.sh`, make executable, and run:
```bash
chmod +x check-structure.sh
./check-structure.sh
```
---
### Exercise 3: Version Update Challenge
Update your provider's Plugin Framework dependency to a specific version.
**Task:**
1. Update to terraform-plugin-framework v1.4.0
2. Verify the update
3. Test that the provider still compiles
4. Revert to v1.5.0
View Answer
```bash
# 1. Update to v1.4.0
go get github.com/hashicorp/terraform-plugin-framework@v1.4.0
go mod tidy
# 2. Verify
grep terraform-plugin-framework go.mod
# Should show: github.com/hashicorp/terraform-plugin-framework v1.4.0
# 3. Test compilation
go build -o terraform-provider-test
# Should succeed (no compilation errors)
# 4. Revert to v1.5.0
go get github.com/hashicorp/terraform-plugin-framework@v1.5.0
go mod tidy
# Verify revert
grep terraform-plugin-framework go.mod
# Should show: github.com/hashicorp/terraform-plugin-framework v1.5.0
```
**Note:** Some features in v1.5.0 may not be available in v1.4.0, so your code might need adjustments for the downgrade to work.
---
## Part 4: Troubleshooting Scenarios
### Scenario 1
You run `terraform init` and get:
```
Error: Failed to query available provider packages
│
│ Could not retrieve the list of available versions for provider YOUR_USERNAME/mycloud
```
**Question:** What are three possible causes and their solutions?
View Answer
**Cause 1: Provider not installed locally**
- **Solution:** Verify installation path matches your OS/architecture
```bash
ls ~/.terraform.d/plugins/registry.terraform.io/YOUR_USERNAME/mycloud/
```
**Cause 2: Username mismatch**
- **Solution:** Ensure username in `main.go`, Terraform config, and installation path all match
**Cause 3: Wrong version specified**
- **Solution:** Check version in `required_providers` matches installation path
```hcl
time = {
source = "registry.terraform.io/YOUR_USERNAME/mycloud"
version = "0.1.0" # Must match installation path
}
```
---
### Scenario 2
After adding a new dependency, you get:
```
go: github.com/new/package@v1.0.0: verifying module: checksum mismatch
```
**Question:** How do you resolve this?
View Answer
**Steps to resolve:**
1. **Clear module cache:**
```bash
go clean -modcache
```
2. **Re-download dependencies:**
```bash
go mod download
```
3. **Tidy up:**
```bash
go mod tidy
```
4. **Verify integrity:**
```bash
go mod verify
```
**If issue persists:**
- Check if you're behind a proxy
- Verify GOPROXY settings
- Ensure go.sum wasn't manually edited
- Try using direct mode: `GOPROXY=direct go mod download`
---
### Scenario 3
Your provider builds successfully but crashes when Terraform runs it with:
```
Error: Plugin did not respond
```
**Question:** What are potential causes and debugging steps?
View Answer
**Potential Causes:**
1. **Wrong provider address** in main.go vs Terraform config
2. **Incomplete provider implementation**
3. **Panic in provider code**
4. **Architecture mismatch** (ARM vs AMD64)
**Debugging Steps:**
1. **Enable debug logging:**
```bash
TF_LOG=DEBUG terraform plan
```
2. **Run provider directly:**
```bash
./terraform-provider-mycloud
```
Should show usage message, not crash
3. **Check provider address:**
```go
// In main.go
Address: "registry.terraform.io/YOUR_USERNAME/mycloud"
```
```hcl
# In main.tf required_providers
source = "registry.terraform.io/YOUR_USERNAME/mycloud"
```
Must match exactly!
4. **Verify architecture:**
```bash
file terraform-provider-mycloud
# Should match your system architecture
```
5. **Check for panics:**
Add recover handlers or run with debugger:
```bash
./terraform-provider-mycloud -debug
```
---
## Part 5: Advanced Challenges
### Challenge 1: Multi-Platform Build
Create a script that builds your provider for multiple platforms.
View Answer
```bash
#!/bin/bash
# build-multi.sh - Build provider for multiple platforms
PROVIDER_NAME="mycloud"
VERSION="0.1.0"
platforms=(
"darwin/amd64"
"darwin/arm64"
"linux/amd64"
"linux/arm64"
"windows/amd64"
)
for platform in "${platforms[@]}"; do
IFS='/' read -r GOOS GOARCH <<< "$platform"
output="dist/terraform-provider-${PROVIDER_NAME}_v${VERSION}_${GOOS}_${GOARCH}"
if [ "$GOOS" = "windows" ]; then
output="${output}.exe"
fi
echo "Building for $GOOS/$GOARCH..."
GOOS=$GOOS GOARCH=$GOARCH go build -o "$output" \
-ldflags="-X main.version=${VERSION}"
if [ $? -eq 0 ]; then
echo "✅ Built: $output"
else
echo "❌ Failed: $GOOS/$GOARCH"
fi
done
echo ""
echo "Build complete! Binaries in dist/"
ls -lh dist/
```
**Usage:**
```bash
chmod +x build-multi.sh
./build-multi.sh
```
---
### Challenge 2: CI/CD Workflow
Design a GitHub Actions workflow for testing and building your provider.
View Answer
Create `.github/workflows/test.yml`:
```yaml
name: Tests
on:
pull_request:
paths-ignore:
- 'README.md'
push:
branches:
- main
permissions:
contents: read
jobs:
test:
name: Test
runs-on: ubuntu-latest
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
go-version: ['1.21', '1.22']
terraform-version: ['1.5', '1.6', '1.7']
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: $
- uses: hashicorp/setup-terraform@v3
with:
terraform_version: $
terraform_wrapper: false
- name: Go mod download
run: go mod download
- name: Go mod verify
run: go mod verify
- name: Go vet
run: go vet ./...
- name: Go build
run: go build -v ./...
- name: Go test
run: go test -v -cover -timeout=120s ./...
```
This workflow:
- Tests multiple Go versions (1.21, 1.22)
- Tests multiple Terraform versions (1.5, 1.6, 1.7)
- Runs on PRs and main branch pushes
- Verifies dependencies
- Runs all tests with coverage
---
## Summary
**Module 3: Development Setup** covered:
- ✅ Go installation and configuration
- ✅ Project scaffolding methods
- ✅ Standard project structure
- ✅ Dependency management with Go modules
- ✅ Hands-on provider development
- ✅ Local testing and verification
**Next Steps:**
- Review any questions you missed
- Revisit corresponding chapters for weak areas
- Complete all hands-on exercises
- Move on to Module 4 when ready
[Continue to Module 4: Provider Basics →](/hashicorp/terraform-provider-development/provider-basics/){: .btn .btn--primary}
---
**Previous:** [← Hands-On Lab](/hashicorp/terraform-provider-development/hands-on-lab/)
*Last updated: June 30, 2026*