diff --git a/examples/namespace/README.md b/examples/namespace/README.md new file mode 100644 index 000000000..35ce76964 --- /dev/null +++ b/examples/namespace/README.md @@ -0,0 +1,33 @@ +--- +display_name: NAMESPACE_NAME +bio: Brief description of what this namespace provides +github: your-github-username +avatar: ./.images/avatar.svg +linkedin: https://www.linkedin.com/in/your-profile +website: https://your-website.com +status: community +--- + +# NAMESPACE_NAME + +Brief description of what this namespace provides. Include information about: + +- What types of templates/modules you offer +- Your focus areas (e.g., specific cloud providers, technologies) +- Any special features or configurations + +## Templates + +List your available templates here: + +- **template-name**: Brief description + +## Modules + +List your available modules here: + +- **module-name**: Brief description + +## Contributing + +If you'd like to contribute to this namespace, please [open an issue](https://github.com/coder/registry/issues) or submit a pull request. diff --git a/examples/templates/README.md b/examples/templates/README.md new file mode 100644 index 000000000..329c57879 --- /dev/null +++ b/examples/templates/README.md @@ -0,0 +1,58 @@ +--- +name: TEMPLATE_NAME +description: A brief description of what this template does +tags: [tag1, tag2, tag3] +icon: /icon/TEMPLATE_NAME.svg +--- + +# TEMPLATE_NAME + +A brief description of what this template provides and its use case. + +## Features + +- Feature 1 +- Feature 2 +- Feature 3 + +## Requirements + +- List any prerequisites or requirements +- Provider-specific requirements (e.g., Docker, AWS credentials) +- Minimum Coder version if applicable + +## Usage + +1. Step-by-step instructions on how to use this template +2. Any configuration that needs to be done +3. How to customize the template + +## Variables + +| Name | Description | Type | Default | Required | +| ----------- | --------------------------- | -------- | ----------------- | -------- | +| example_var | Description of the variable | `string` | `"default_value"` | no | + +## Resources Created + +- List of resources that will be created +- Brief description of each resource + +## Customization + +Explain how users can customize this template for their needs: + +- How to modify the startup script +- How to add additional software +- How to configure different providers + +## Troubleshooting + +### Common Issues + +- Issue 1 and its solution +- Issue 2 and its solution + +## Contributing + +Contributions are welcome! Please see the [contributing guidelines](../../CONTRIBUTING.md) for more information. diff --git a/examples/templates/main.tf b/examples/templates/main.tf new file mode 100644 index 000000000..27bfb8970 --- /dev/null +++ b/examples/templates/main.tf @@ -0,0 +1,172 @@ +terraform { + required_providers { + coder = { + source = "coder/coder" + } + # Add your provider here (e.g., docker, aws, gcp, azure) + # docker = { + # source = "kreuzwerker/docker" + # } + } +} + +locals { + username = data.coder_workspace_owner.me.name +} + +# Add your variables here +# variable "example_var" { +# default = "default_value" +# description = "Description of the variable" +# type = string +# } + +# Configure your provider here +# provider "docker" { +# host = var.docker_socket != "" ? var.docker_socket : null +# } + +data "coder_provisioner" "me" {} +data "coder_workspace" "me" {} +data "coder_workspace_owner" "me" {} + +resource "coder_agent" "main" { + arch = data.coder_provisioner.me.arch + os = "linux" + startup_script = <<-EOT + set -e + + # Prepare user home with default files on first start. + if [ ! -f ~/.init_done ]; then + cp -rT /etc/skel ~ + touch ~/.init_done + fi + + # Add any commands that should be executed at workspace startup here + EOT + + # These environment variables allow you to make Git commits right away after creating a + # workspace. Note that they take precedence over configuration defined in ~/.gitconfig! + # You can remove this block if you'd prefer to configure Git manually or using + # dotfiles. (see docs/dotfiles.md) + env = { + GIT_AUTHOR_NAME = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name) + GIT_AUTHOR_EMAIL = "${data.coder_workspace_owner.me.email}" + GIT_COMMITTER_NAME = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name) + GIT_COMMITTER_EMAIL = "${data.coder_workspace_owner.me.email}" + } + + # The following metadata blocks are optional. They are used to display + # information about your workspace in the dashboard. You can remove them + # if you don't want to display any information. + # For basic templates, you can remove the "display_apps" block. + metadata { + display_name = "CPU Usage" + key = "0_cpu_usage" + script = "coder stat cpu" + interval = 10 + timeout = 1 + } + + metadata { + display_name = "RAM Usage" + key = "1_ram_usage" + script = "coder stat mem" + interval = 10 + timeout = 1 + } + + metadata { + display_name = "Home Disk" + key = "3_home_disk" + script = "coder stat disk --path $${HOME}" + interval = 60 + timeout = 1 + } + + display_apps { + vscode = true + vscode_insiders = false + ssh_helper = false + port_forwarding_helper = true + web_terminal = true + } +} + +# Add your resources here (e.g., docker container, VM, etc.) +# resource "docker_image" "main" { +# name = "codercom/enterprise-base:ubuntu" +# } + +# resource "docker_container" "workspace" { +# count = data.coder_workspace.me.start_count +# image = docker_image.main.image_id +# # Uses lower() to avoid Docker restriction on container names. +# name = "coder-${data.coder_workspace_owner.me.name}-${lower(data.coder_workspace.me.name)}" +# # Hostname makes the shell more user friendly: coder@my-workspace:~$ +# hostname = data.coder_workspace.me.name +# # Use the docker gateway if the access URL is 127.0.0.1 +# entrypoint = ["sh", "-c", replace(coder_agent.main.init_script, "/localhost|127\.0\.0\.1/", "host.docker.internal")] +# env = ["CODER_AGENT_TOKEN=${coder_agent.main.token}"] +# host { +# host = "host.docker.internal" +# ip = "host-gateway" +# } +# volumes { +# container_path = "/home/${local.username}" +# volume_name = docker_volume.home_volume[0].name +# read_only = false +# } +# # Add labels in Docker to keep track of orphan resources. +# labels { +# label = "coder.owner" +# value = data.coder_workspace_owner.me.name +# } +# labels { +# label = "coder.owner_id" +# value = data.coder_workspace_owner.me.id +# } +# labels { +# label = "coder.workspace_id" +# value = data.coder_workspace.me.id +# } +# labels { +# label = "coder.workspace_name" +# value = data.coder_workspace.me.name +# } +# } + +# resource "docker_volume" "home_volume" { +# count = data.coder_workspace.me.start_count +# name = "coder-${data.coder_workspace_owner.me.name}-${data.coder_workspace.me.name}-home" +# # Protect the volume from being deleted due to changes in attributes. +# lifecycle { +# ignore_changes = all +# } +# # Add labels in Docker to keep track of orphan resources. +# labels { +# label = "coder.owner" +# value = data.coder_workspace_owner.me.name +# } +# labels { +# label = "coder.owner_id" +# value = data.coder_workspace_owner.me.id +# } +# labels { +# label = "coder.workspace_id" +# value = data.coder_workspace.me.id +# } +# labels { +# label = "coder.workspace_name" +# value = data.coder_workspace.me.name +# } +# } + +resource "coder_metadata" "workspace_info" { + resource_id = coder_agent.main.id + + item { + key = "TEMPLATE_NAME" + value = "TEMPLATE_NAME" + } +} diff --git a/scripts/new_module.sh b/scripts/new_module.sh index bc98d9ee3..633338481 100755 --- a/scripts/new_module.sh +++ b/scripts/new_module.sh @@ -29,6 +29,28 @@ if [ -d "registry/$NAMESPACE/modules/$MODULE_NAME" ]; then echo "Please choose a different name" exit 1 fi + +# Create namespace directory if it doesn't exist +if [ ! -d "registry/$NAMESPACE" ]; then + echo "Creating namespace directory: registry/$NAMESPACE" + mkdir -p "registry/$NAMESPACE" + + # Create namespace README if it doesn't exist + if [ ! -f "registry/$NAMESPACE/README.md" ]; then + echo "Creating namespace README: registry/$NAMESPACE/README.md" + cp "examples/namespace/README.md" "registry/$NAMESPACE/README.md" + + # Replace NAMESPACE_NAME placeholder in the README + if [[ "$OSTYPE" == "darwin"* ]]; then + # macOS + sed -i '' "s/NAMESPACE_NAME/${NAMESPACE}/g" "registry/$NAMESPACE/README.md" + else + # Linux + sed -i "s/NAMESPACE_NAME/${NAMESPACE}/g" "registry/$NAMESPACE/README.md" + fi + fi +fi + mkdir -p "registry/${NAMESPACE}/modules/${MODULE_NAME}" # Copy required files from the example module diff --git a/scripts/new_template.sh b/scripts/new_template.sh new file mode 100755 index 000000000..b06d108ba --- /dev/null +++ b/scripts/new_template.sh @@ -0,0 +1,79 @@ +#!/usr/bin/env bash + +# This script creates a new sample template directory with required files +# Run it like: ./scripts/new_template.sh my-namespace/my-template + +TEMPLATE_ARG=$1 + +# Check if they are in the root directory +if [ ! -d "registry" ]; then + echo "Please run this script from the root directory of the repository" + echo "Usage: ./scripts/new_template.sh /" + exit 1 +fi + +# check if template name is in the format / +if ! [[ "$TEMPLATE_ARG" =~ ^[a-z0-9_-]+/[a-z0-9_-]+$ ]]; then + echo "Template name must be in the format /" + echo "Usage: ./scripts/new_template.sh /" + exit 1 +fi + +# Extract the namespace and template name +NAMESPACE=$(echo "$TEMPLATE_ARG" | cut -d'/' -f1) +TEMPLATE_NAME=$(echo "$TEMPLATE_ARG" | cut -d'/' -f2) + +# Check if the template already exists +if [ -d "registry/$NAMESPACE/templates/$TEMPLATE_NAME" ]; then + echo "Template at registry/$NAMESPACE/templates/$TEMPLATE_NAME already exists" + echo "Please choose a different name" + exit 1 +fi + +# Create namespace directory if it doesn't exist +if [ ! -d "registry/$NAMESPACE" ]; then + echo "Creating namespace directory: registry/$NAMESPACE" + mkdir -p "registry/$NAMESPACE" + + # Create namespace README if it doesn't exist + if [ ! -f "registry/$NAMESPACE/README.md" ]; then + echo "Creating namespace README: registry/$NAMESPACE/README.md" + cp "examples/namespace/README.md" "registry/$NAMESPACE/README.md" + + # Replace NAMESPACE_NAME placeholder in the README + if [[ "$OSTYPE" == "darwin"* ]]; then + # macOS + sed -i '' "s/NAMESPACE_NAME/${NAMESPACE}/g" "registry/$NAMESPACE/README.md" + else + # Linux + sed -i "s/NAMESPACE_NAME/${NAMESPACE}/g" "registry/$NAMESPACE/README.md" + fi + fi +fi + +# Create the template directory structure +mkdir -p "registry/${NAMESPACE}/templates/${TEMPLATE_NAME}" + +# Copy required files from the example template +cp -r examples/templates/* "registry/${NAMESPACE}/templates/${TEMPLATE_NAME}/" + +# Change to template directory +cd "registry/${NAMESPACE}/templates/${TEMPLATE_NAME}" + +# Detect OS and replace placeholders +if [[ "$OSTYPE" == "darwin"* ]]; then + # macOS + sed -i '' "s/TEMPLATE_NAME/${TEMPLATE_NAME}/g" main.tf + sed -i '' "s/TEMPLATE_NAME/${TEMPLATE_NAME}/g" README.md +else + # Linux + sed -i "s/TEMPLATE_NAME/${TEMPLATE_NAME}/g" main.tf + sed -i "s/TEMPLATE_NAME/${TEMPLATE_NAME}/g" README.md +fi + +echo "Template scaffolded successfully at registry/${NAMESPACE}/templates/${TEMPLATE_NAME}" +echo "Next steps:" +echo "1. Edit main.tf to add your infrastructure resources" +echo "2. Update README.md with template-specific information" +echo "3. Test your template with 'coder templates push'" +echo "4. Consider adding an icon at .icons/${TEMPLATE_NAME}.svg"