Google-cloud-sdk and installing extra components?

I tried installing extra components to gcloud and got this error:

$ gcloud components install app-engine-python
ERROR: (gcloud.components.install) You cannot perform this action because this Cloud SDK installation is managed by an external package manager.
Please consider using a separate installation of the Cloud SDK created through the default mechanism described at: https://cloud.google.com/sdk/

I expected something like this, and went to https://github.com/NixOS/nixpkgs/tree/master/pkgs/tools/admin/google-cloud-sdk to see if there’s already a way to specify which extra components to install, but I couldn’t see any. I found this open issue without any comments: https://github.com/NixOS/nixpkgs/issues/99280. My question is this: Is there a way to install gcloud with extra components already? Or is there an alternative to use gcloud with extra components on NixOS?

2 Likes

Does anyone knows a way to do this?

I’m actually trying to figure this out myself as I’ve encountered a bug with the app-gradle-plugin for GCE and the suggested workaround was to install the app-engine-java component: https://github.com/GoogleCloudPlatform/app-gradle-plugin/issues/393

I ran into this as well.

As a workaround I use the following shell.nix:

{ pkgs ? import <nixpkgs> {} }:

(pkgs.buildFHSUserEnv {
  name = "google-cloud-sdk";

  targetPkgs = pkgs: [
    pkgs.python3
  ];
  
}).env

and inside that shell use the ‘regular’ gcloud tool downloaded from Installing Cloud SDK  |  Cloud SDK Documentation  |  Google Cloud

I would also love a declarative way to do this though :wink:

1 Like

WARNING: read through it carefully and use at your own risk and be aware that I am not an expert in neither nix nor gcloud.

This is declarative, but extremely hacky and impure (depends on gcloud accessing the network). Note that it uses __noChroot = true, and therefore you must allow sandboxing to be disabled (e.g. nix-shell --option sandbox relaxed ran by a user in the trusted-users configuration if using a multi-user nix install).

Change the additional_components = ... line to whatever components you need.

I’ve only tested that gcloud alpha code dev runs successfully on this nixpkgs revision https://github.com/NixOS/nixpkgs/archive/8588b14a397e045692d0a87192810b6dddf53003.tar.gz ( contains google-cloud-sdk at version 362.0.0).
I’m also not sure if all of the shell steps are necessary, I pretty much just copied some of what was in the google-cloud-sdk nix expression without deep understanding.

{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
    nativeBuildInputs = [
#        this is a very inpure hack to get gcloud additional components working with nix. I'm not sure if they will
#        function properly, but if not, the errors *should* be quite obvious (e.g. path not found or permission denied).
#        todo when nixpkgs packages these additional components properly, delete this hack.
        (
            let
                openssl = pkgs.openssl;
                python = pkgs.python;
                pythonEnv = python.withPackages (p: [
                    openssl
                    p.cffi
                    p.cryptography
                    p.crcmod
                ]);
            in (pkgs.google-cloud-sdk.override {inherit openssl; inherit python;}).overrideAttrs(oldAttrs:
                let
                    additional_components = "kubectl minikube skaffold";
                    env_fix = {
                        cloudsdk_python = "${pythonEnv}/bin/python";
                        python_path = "${pythonEnv}/${python.sitePackages}:$PYTHONPATH";
                        path = "${openssl.bin}/bin:$PATH";
                    };
                in {
                    __noChroot = true;
                    preInstall = ''
                        src_dir="$PWD"
                        export \
                            CLOUDSDK_CONFIG="$src_dir/.config" \
                            CLOUDSDK_PYTHON="${env_fix.cloudsdk_python}" \
                            PYTHONPATH="${env_fix.python_path}" \
                            PATH="${env_fix.path}"
                        mkdir -p "$out"
                        pushd "$out"
                        "$src_dir/bin/gcloud" components install ${additional_components}
                        popd
                        # At this point, the $CLOUDSDK_CONFIG dir contains nothing useful, so we remove it to save storage and
                        # to avoid any confusion with the CLOUDSDK_CONFIG runtime value.
                        rm -rf "$CLOUDSDK_CONFIG"
                    '';
                     postInstall = ''
                        for program in ${additional_components}; do
                           programPath="$out/google-cloud-sdk/bin/$program"
                           wrapProgram "$programPath" \
                               --set CLOUDSDK_PYTHON "${env_fix.cloudsdk_python}" \
                               --prefix PYTHONPATH : "${env_fix.python_path}" \
                               --prefix PATH : "${env_fix.path}"
                           ln -s "$programPath" "$out/bin/$program"
                        done
                     '';
                }
            )
        )
    ];
}
Hosted by Flying Circus.