Jeremy Dormitzer
3537134c23
This commit adds the ability to run a Terraform console at a specified path in a comint buffer, making it easier to interactively explore and manage Terraform state.
91 lines
4.0 KiB
EmacsLisp
91 lines
4.0 KiB
EmacsLisp
;; -*- lexical-binding: t; -*-
|
|
|
|
;; Configuration as code!
|
|
(use-package terraform-mode
|
|
:mode "\\.tf\\'"
|
|
:config
|
|
(defun devdocs-terraform-resource-string (resource type)
|
|
"Returns the devdocs for Terraform resource RESOURCE of type TYPE (\"data\" or \"resource\")as a string."
|
|
(devdocs-as-string resource "terraform" type))
|
|
|
|
(with-eval-after-load 'devdocs
|
|
(add-to-list 'devdocs-entry-aliases '("aws_alb" . "aws_lb")))
|
|
|
|
(defun terraform-block-metadata-at-pos (pos)
|
|
(let* ((parser (treesit-parser-create 'hcl))
|
|
(current-node (treesit-node-at pos parser))
|
|
(block (treesit-node-top-level current-node "block"))
|
|
(capture (when block
|
|
(treesit-query-capture block
|
|
'((block (identifier) @type (:match "^\\(data\\|resource\\)$" @type)
|
|
(string_lit (_) (template_literal) @name (_)))))))
|
|
(capture (let ((-compare-fn (lambda (a b) (eq (car a) (car b)))))
|
|
(-distinct capture))))
|
|
(-map (lambda (r) (cons (car r) (treesit-node-text (cdr r) t))) capture)))
|
|
|
|
(defun terraform-block-metadata-at-point ()
|
|
(terraform-block-metadata-at-pos (point)))
|
|
|
|
(defun terraform-devdocs-eldoc-function (cb)
|
|
(when-let* ((metadata (terraform-block-metadata-at-point))
|
|
(resource-name (alist-get 'name metadata))
|
|
(resource-type (alist-get 'type metadata))
|
|
(doc (devdocs-terraform-resource-string resource-name resource-type))
|
|
(summary (with-temp-buffer
|
|
(insert doc)
|
|
(goto-char (point-min))
|
|
(forward-line)
|
|
(while (and (looking-at (rx space) t) (not (eobp)))
|
|
(forward-line))
|
|
(buffer-substring-no-properties (line-beginning-position) (line-end-position)))))
|
|
(funcall cb doc :echo summary)))
|
|
|
|
(defun terraform-setup-eldoc ()
|
|
(add-hook 'eldoc-documentation-functions #'terraform-devdocs-eldoc-function nil t))
|
|
|
|
(add-hook 'terraform-mode-hook #'terraform-setup-eldoc)
|
|
|
|
(defun find-terraform-root ()
|
|
"Returns the highest-level parent directory containing a .tf file."
|
|
(let ((current-dir default-directory)
|
|
(root nil))
|
|
(while (and (not (string-match locate-dominating-stop-dir-regexp current-dir))
|
|
(f-glob "*.tf" current-dir))
|
|
(setq root current-dir)
|
|
(setq current-dir (f-parent current-dir)))
|
|
(when root (file-name-as-directory root))))
|
|
|
|
;; Use root terraform module to resolve providers
|
|
(defun terraform-provider-ns-advice (oldfn &rest args)
|
|
(let ((dir (or (find-terraform-root) default-directory)))
|
|
(let ((default-directory dir))
|
|
(apply oldfn args))))
|
|
|
|
(defvar terraform-default-aws-profile "default"
|
|
"The default AWS profile to use when running terraform commands.")
|
|
|
|
(defun terraform-console (path)
|
|
"Run a Terraform console at `path' in a comint buffer."
|
|
(interactive (list (read-directory-name "Path: " (find-terraform-root))))
|
|
(let* ((process-environment (cons (format "AWS_PROFILE=%s" terraform-default-aws-profile)
|
|
process-environment))
|
|
(default-directory (expand-file-name path))
|
|
(program "terraform")
|
|
(switches (list "console"))
|
|
(expected-buf-name (apply #'make-comint program program nil switches)))
|
|
(comint-run "terraform" (list "console"))
|
|
(with-current-buffer expected-buf-name
|
|
(setq-local comint-prompt-read-only t
|
|
comint-process-echoes t))))
|
|
|
|
(advice-add 'terraform--get-resource-provider-namespace :around #'terraform-provider-ns-advice))
|
|
|
|
(defun terraform-jump-to-plan ()
|
|
"Jump to the top of the plan output in a buffer showing a terraform plan."
|
|
(interactive)
|
|
(when (eq major-mode 'vterm-mode)
|
|
(vterm-copy-mode))
|
|
(search-backward "Terraform will perform the following actions:"))
|
|
|
|
(provide 'init-terraform)
|