issue with creating context in interactive mode (hcloud: context create is an interactive command)
TL;DR
not able to use HCLOUD_TOKEN while running hcloud create context
Expected behavior
when running HCLOUD_TOKEN="x" hcloud context create dummy this should work and use the token provided in the environment var.
Observed behavior
i get the error:
hcloud: context create is an interactive command
Minimal working example
we use this in our gitlab ci pipeline where hcloud is installed via brew brew install hcloud:
HCLOUD_TOKEN="${TF_VAR_hcloud_token}" hcloud context create gitlab-ci <<<"Y"
Log output
$ HCLOUD_TOKEN="${TF_VAR_hcloud_token}" hcloud context create gitlab-ci <<<"Y"
hcloud: context create is an interactive command
Cleaning up project directory and file based variables 00:01
ERROR: Job failed: exit code 1
Additional information
See commend as there the links are working
While checking the issue and diving into the code i found the following, keep in mind i am not sure if this is the case and is just an assumption :)
While this already happened before and saw it was fixed in the past already multiple times i think it has been broken by the last update by @phm07 with the change from if !ui.StdoutIsTerminal() { to if !s.Terminal().StdoutIsTerminal() { in commit: https://github.com/hetznercloud/cli/commit/0db50460b1c88f99b0fb05b87d525a5bd91d140d
I am not a go developer so this is just a suggestion and i see that it has been changed what could of course explain why? Is it not a better idea to skip the interactive check when the os environment variable is provided?
Hey @jnovermars,
I can not reproduce the issue on the latest version or on main. I do use Linux though. You are running your gitlab-ci pipeline on macOS?
What is the output of the following commands?
hcloud version- To verify that you use an up to date versionwhich hcloud- To make sure that the expected binary from brew is usedecho $0- To get the name of the current shell (probalyzshon Mac)
For reproducing I used the following command:
$ HCLOUD_CONFIG=hcloud-cli-819.toml HCLOUD_TOKEN=$(openssl rand -hex 64 | head -c 64) bash -c "hcloud context create foo <<<'Y'"
The HCLOUD_TOKEN environment variable is set. Do you want to use the token from HCLOUD_TOKEN for the new context? (Y/n): Context foo created and activated
Its also not necessary to create a context in your CI pipeline, you can do everything with environment variables and or flags if you want to.
It is easy to reproduce it in docker, i runned the commands you asked:
docker build -t test-hcloud . && docker run test-hcloud bash -c "hcloud version && which hcloud && echo \$0"
hcloud version: hcloud v1.45.0
which hcloud: /home/linuxbrew/.linuxbrew/bin/hcloud
echo $0: bash
i quicky created a small version of our docker file, and you are totally right that for CI pipeline the commands could run without the context. But i found this and think this is a bug as the expectation is that it could run without TTY but still it is required.
I converted your command to run it in docker:
docker build -t test-hcloud . && docker run test-hcloud bash -c "HCLOUD_CONFIG=hcloud-cli-819.toml HCLOUD_TOKEN=\$(openssl rand -hex 64 | head -c 64) hcloud context create foo <<<'Y'"
The docker file:
Big disclaimer, this is a brutally stripped docker file and just for demo purposes to run the hcloud command
FROM ubuntu:24.04
ENV TZ="Europe/Amsterdam"
ENV DEBIAN_FRONTEND="noninteractive"
# Install updates and dependencies
RUN apt update -y && apt install --no-install-recommends -y -q \
curl \
git \
nano \
build-essential \
wget \
dirmngr \
apt-transport-https \
gnupg \
lsb-release \
ca-certificates \
software-properties-common \
&& apt-get clean
## second stage: Brew
ENV HOMEBREW_NO_AUTO_UPDATE=1
# Install brew
RUN apt-get update && \
apt-get install -y -q --allow-unauthenticated \
git \
sudo
RUN useradd -m -s /bin/zsh linuxbrew && \
usermod -aG sudo linuxbrew && \
mkdir -p /home/linuxbrew/.linuxbrew && \
chown -R linuxbrew: /home/linuxbrew/.linuxbrew
USER linuxbrew
RUN /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
USER root
RUN chown -R $CONTAINER_USER: /home/linuxbrew/.linuxbrew
ENV PATH="/home/linuxbrew/.linuxbrew/bin:${PATH}"
USER linuxbrew
RUN brew update
RUN brew install gcc
USER root
## Setup linuxbrew user
RUN mkdir -p /home/linuxbrew/workspace
WORKDIR /home/linuxbrew/workspace
USER linuxbrew
## third stage: install packages
## Install Terraform/OpenTofu gitlab scripts
USER root
RUN apt update -y && apt install --no-install-recommends -y -q \
idn2 \
openssh-client \
&& apt-get clean
USER linuxbrew
## Install Packer, kubectl, hcloud, jq
RUN brew install hcloud
I agree that we should support non-interactive mode, I think have an "assume yes" to bypass any yes/no prompt would be helpful in this scenario. But this might require a broader change across the CLI to support a such a global flag.
This is currently low priority, as one can always use the HCLOUD_TOKEN environment variable when running a script. Using a context for a script seem to be a really specific use case.
That is indeed the workaround we use now
Creating a context in non-interactive mode would mean that you would have to pass the token as a command argument. This is potentially unsafe and bad practice, since the token would then be stored in your shell history, even if you deleted the context. (Edit: Getting it from the environment, like you suggested, would be viable though. We would still need an extra flag then)
As a workaround, you can manually create contexts by manually appending to ~/.config/hcloud/cli.toml. The config is structured in such a way that appending a context does not break it.
@jnovermars Can you try installing hcloud with:
go install github.com/hetznercloud/cli/cmd/hcloud@token-from-env
Then you can try using the following command:
HCLOUD_TOKEN="x" hcloud context create dummy --token-from-env
This should allow you to create a context using the CLI in a non-interactive TTY. Although be beware that this is not the recommended method, as it will store your token plain on disk and just using the HCLOUD_TOKEN environment variable is more secure (and also usually more convenient) than using contexts.
This issue has been marked as stale because it has not had recent activity. The bot will close the issue if no further action occurs.