btrbk: add mainProgram
[NixPkgs.git] / pkgs / by-name / az / azure-cli / package.nix
blob4744b7d109eed733939b9f2adcb61ac94c95187b
2   lib,
3   callPackage,
4   callPackages,
5   stdenvNoCC,
6   fetchurl,
7   fetchFromGitHub,
8   runCommand,
9   installShellFiles,
10   python3,
11   writeScriptBin,
13   black,
14   isort,
15   mypy,
16   makeWrapper,
18   # Whether to include patches that enable placing certain behavior-defining
19   # configuration files in the Nix store.
20   withImmutableConfig ? true,
22   # List of extensions/plugins to include.
23   withExtensions ? [ ],
25   azure-cli,
28 let
29   version = "2.65.0";
31   src = fetchFromGitHub {
32     name = "azure-cli-${version}-src";
33     owner = "Azure";
34     repo = "azure-cli";
35     rev = "azure-cli-${version}";
36     hash = "sha256-IeiAB0AI6KNpXwx2Iv55LBARcwemakbblFlbfLheuGE=";
37   };
39   # put packages that needs to be overridden in the py package scope
40   py = callPackage ./python-packages.nix { inherit src version python3; };
42   # Builder for Azure CLI extensions. Extensions are Python wheels that
43   # outside of nix would be fetched by the CLI itself from various sources.
44   mkAzExtension =
45     {
46       pname,
47       version,
48       url,
49       hash,
50       description,
51       ...
52     }@args:
53     python3.pkgs.buildPythonPackage (
54       {
55         format = "wheel";
56         src = fetchurl { inherit url hash; };
57         meta = {
58           inherit description;
59           inherit (azure-cli.meta) platforms maintainers;
60           homepage = "https://github.com/Azure/azure-cli-extensions";
61           changelog = "https://github.com/Azure/azure-cli-extensions/blob/main/src/${pname}/HISTORY.rst";
62           license = lib.licenses.mit;
63           sourceProvenance = [ lib.sourceTypes.fromSource ];
64         } // args.meta or { };
65       }
66       // (removeAttrs args [
67         "url"
68         "hash"
69         "description"
70         "meta"
71       ])
72     );
74   extensions-generated = lib.mapAttrs (name: ext: mkAzExtension ext) (
75     builtins.fromJSON (builtins.readFile ./extensions-generated.json)
76   );
77   extensions-manual = callPackages ./extensions-manual.nix {
78     inherit mkAzExtension;
79     python3Packages = python3.pkgs;
80   };
81   extensions = extensions-generated // extensions-manual;
83   extensionDir = stdenvNoCC.mkDerivation {
84     name = "azure-cli-extensions";
85     dontUnpack = true;
86     installPhase =
87       let
88         namePaths = map (p: "${p.pname},${p}/${python3.sitePackages}") withExtensions;
89       in
90       ''
91         for line in ${lib.concatStringsSep " " namePaths}; do
92           name=$(echo $line | cut -d',' -f1)
93           path=$(echo $line | cut -d',' -f2)
94           mkdir -p $out/$name
95           for f in $(ls $path); do
96             ln -s $path/$f $out/$name/$f
97           done
98         done
99       '';
100   };
103 py.pkgs.toPythonApplication (
104   py.pkgs.buildAzureCliPackage rec {
105     pname = "azure-cli";
106     inherit version src;
108     sourceRoot = "${src.name}/src/azure-cli";
110     nativeBuildInputs = [
111       installShellFiles
112       py.pkgs.argcomplete
113     ];
115     # Dependencies from:
116     # https://github.com/Azure/azure-cli/blob/azure-cli-2.62.0/src/azure-cli/setup.py#L52
117     # Please, keep ordered by upstream file order. It facilitates reviews.
118     propagatedBuildInputs =
119       with py.pkgs;
120       [
121         antlr4-python3-runtime
122         azure-appconfiguration
123         azure-batch
124         azure-cli-core
125         azure-cosmos
126         azure-data-tables
127         azure-datalake-store
128         azure-graphrbac
129         azure-keyvault-administration
130         azure-keyvault-certificates
131         azure-keyvault-keys
132         azure-keyvault-secrets
133         azure-mgmt-advisor
134         azure-mgmt-apimanagement
135         azure-mgmt-appconfiguration
136         azure-mgmt-appcontainers
137         azure-mgmt-applicationinsights
138         azure-mgmt-authorization
139         azure-mgmt-batchai
140         azure-mgmt-batch
141         azure-mgmt-billing
142         azure-mgmt-botservice
143         azure-mgmt-cdn
144         azure-mgmt-cognitiveservices
145         azure-mgmt-compute
146         azure-mgmt-containerinstance
147         azure-mgmt-containerregistry
148         azure-mgmt-containerservice
149         azure-mgmt-cosmosdb
150         azure-mgmt-databoxedge
151         azure-mgmt-datamigration
152         azure-mgmt-devtestlabs
153         azure-mgmt-dns
154         azure-mgmt-eventgrid
155         azure-mgmt-eventhub
156         azure-mgmt-extendedlocation
157         azure-mgmt-hdinsight
158         azure-mgmt-imagebuilder
159         azure-mgmt-iotcentral
160         azure-mgmt-iothub
161         azure-mgmt-iothubprovisioningservices
162         azure-mgmt-keyvault
163         azure-mgmt-kusto
164         azure-mgmt-loganalytics
165         azure-mgmt-managedservices
166         azure-mgmt-managementgroups
167         azure-mgmt-maps
168         azure-mgmt-marketplaceordering
169         azure-mgmt-media
170         azure-mgmt-monitor
171         azure-mgmt-msi
172         azure-mgmt-netapp
173         azure-mgmt-policyinsights
174         azure-mgmt-privatedns
175         azure-mgmt-rdbms
176         azure-mgmt-recoveryservicesbackup
177         azure-mgmt-recoveryservices
178         azure-mgmt-redis
179         azure-mgmt-redhatopenshift
180         azure-mgmt-resource
181         azure-mgmt-search
182         azure-mgmt-security
183         azure-mgmt-servicebus
184         azure-mgmt-servicefabricmanagedclusters
185         azure-mgmt-servicelinker
186         azure-mgmt-servicefabric
187         azure-mgmt-signalr
188         azure-mgmt-sqlvirtualmachine
189         azure-mgmt-sql
190         azure-mgmt-storage
191         azure-mgmt-synapse
192         azure-mgmt-trafficmanager
193         azure-mgmt-web
194         azure-monitor-query
195         azure-multiapi-storage
196         azure-storage-common
197         azure-synapse-accesscontrol
198         azure-synapse-artifacts
199         azure-synapse-managedprivateendpoints
200         azure-synapse-spark
201         chardet
202         colorama
203       ]
204       ++ lib.optional stdenv.hostPlatform.isLinux distro
205       ++ [
206         fabric
207         javaproperties
208         jsondiff
209         packaging
210         pycomposefile
211         pygithub
212         pynacl
213         scp
214         semver
215         six
216         sshtunnel
217         tabulate
218         urllib3
219         websocket-client
220         xmltodict
222         # Other dependencies
223         pyopenssl # Used at: https://github.com/Azure/azure-cli/blob/azure-cli-2.62.0/src/azure-cli/azure/cli/command_modules/servicefabric/custom.py#L11
224         setuptools # ModuleNotFoundError: No module named 'pkg_resources'
225       ]
226       ++ lib.optionals (!withImmutableConfig) [
227         # pip is required to install extensions locally, but it's not needed if
228         # we're using the default immutable configuration.
229         pip
230       ]
231       ++ lib.concatMap (extension: extension.propagatedBuildInputs) withExtensions;
233     postInstall =
234       lib.optionalString (stdenvNoCC.buildPlatform.canExecute stdenvNoCC.hostPlatform) ''
235         installShellCompletion --cmd az \
236           --bash <(register-python-argcomplete az --shell bash) \
237           --zsh <(register-python-argcomplete az --shell zsh) \
238           --fish <(register-python-argcomplete az --shell fish)
239       ''
240       + lib.optionalString withImmutableConfig ''
241         export HOME=$TMPDIR
242         $out/bin/az --version
243         mkdir -p $out/etc/azure
244         mv $TMPDIR/.azure/commandIndex.json $out/etc/azure/commandIndex.json
245         mv $TMPDIR/.azure/versionCheck.json $out/etc/azure/versionCheck.json
246       ''
247       + ''
248         # remove garbage
249         rm $out/bin/az.bat
250         rm $out/bin/az.completion.sh
251       '';
253     # wrap the executable so that the python packages are available
254     # it's just a shebang script which calls `python -m azure.cli "$@"`
255     postFixup =
256       ''
257         wrapProgram $out/bin/az \
258       ''
259       + lib.optionalString withImmutableConfig ''
260         --set AZURE_IMMUTABLE_DIR $out/etc/azure \
261       ''
262       + lib.optionalString (withExtensions != [ ]) ''
263         --set AZURE_EXTENSION_DIR ${extensionDir} \
264       ''
265       + ''
266         --set PYTHONPATH "${python3.pkgs.makePythonPath propagatedBuildInputs}:$out/${python3.sitePackages}"
267       '';
269     doInstallCheck = true;
270     installCheckPhase = ''
271       export HOME=$TMPDIR
273       $out/bin/az --version
274       $out/bin/az self-test
275     '';
277     # ensure these namespaces are able to be accessed
278     pythonImportsCheck = [
279       "azure.batch"
280       "azure.cli.core"
281       "azure.cli.telemetry"
282       "azure.cosmos"
283       "azure.datalake.store"
284       "azure.graphrbac"
285       "azure.keyvault"
286       "azure.mgmt.advisor"
287       "azure.mgmt.apimanagement"
288       "azure.mgmt.applicationinsights"
289       "azure.mgmt.appconfiguration"
290       "azure.mgmt.appcontainers"
291       "azure.mgmt.authorization"
292       "azure.mgmt.batch"
293       "azure.mgmt.batchai"
294       "azure.mgmt.billing"
295       "azure.mgmt.botservice"
296       "azure.mgmt.cdn"
297       "azure.mgmt.cognitiveservices"
298       "azure.mgmt.compute"
299       "azure.mgmt.containerinstance"
300       "azure.mgmt.containerregistry"
301       "azure.mgmt.containerservice"
302       "azure.mgmt.cosmosdb"
303       "azure.mgmt.datamigration"
304       "azure.mgmt.devtestlabs"
305       "azure.mgmt.dns"
306       "azure.mgmt.eventgrid"
307       "azure.mgmt.eventhub"
308       "azure.mgmt.hdinsight"
309       "azure.mgmt.imagebuilder"
310       "azure.mgmt.iotcentral"
311       "azure.mgmt.iothub"
312       "azure.mgmt.iothubprovisioningservices"
313       "azure.mgmt.keyvault"
314       "azure.mgmt.kusto"
315       "azure.mgmt.loganalytics"
316       "azure.mgmt.managedservices"
317       "azure.mgmt.managementgroups"
318       "azure.mgmt.maps"
319       "azure.mgmt.marketplaceordering"
320       "azure.mgmt.media"
321       "azure.mgmt.monitor"
322       "azure.mgmt.msi"
323       "azure.mgmt.netapp"
324       "azure.mgmt.policyinsights"
325       "azure.mgmt.privatedns"
326       "azure.mgmt.rdbms"
327       "azure.mgmt.recoveryservices"
328       "azure.mgmt.recoveryservicesbackup"
329       "azure.mgmt.redis"
330       "azure.mgmt.resource"
331       "azure.mgmt.search"
332       "azure.mgmt.security"
333       "azure.mgmt.servicebus"
334       "azure.mgmt.servicefabric"
335       "azure.mgmt.signalr"
336       "azure.mgmt.sql"
337       "azure.mgmt.sqlvirtualmachine"
338       "azure.mgmt.storage"
339       "azure.mgmt.trafficmanager"
340       "azure.mgmt.web"
341       "azure.monitor.query"
342       "azure.storage.common"
343     ];
345     passthru = {
346       inherit extensions;
347       withExtensions = extensions: azure-cli.override { withExtensions = extensions; };
348       tests = {
349         # Test the package builds with some extensions configured, and the
350         # wanted extensions are recognized by the CLI and listed in the output.
351         azWithExtensions =
352           let
353             extensions = with azure-cli.extensions; [
354               aks-preview
355               azure-devops
356               rdbms-connect
357             ];
358             extensionNames = map (ext: ext.pname) extensions;
359             az = (azure-cli.withExtensions extensions);
360           in
361           runCommand "test-az-with-extensions" { } ''
362             export HOME=$TMPDIR
363             ${lib.getExe az} extension list > $out
364             for ext in ${lib.concatStringsSep " " extensionNames}; do
365               if ! grep -q $ext $out; then
366                 echo "Extension $ext not found in list"
367                 exit 1
368               fi
369             done
370           '';
371         # Test the package builds with mutable config.
372         # TODO: Maybe we can install an extension from local python wheel to
373         #       check mutable extension install still works.
374         azWithMutableConfig =
375           let
376             az = azure-cli.override { withImmutableConfig = false; };
377           in
378           runCommand "test-az-with-immutable-config" { } ''
379             export HOME=$TMPDIR
380             ${lib.getExe az} --version || exit 1
381             touch $out
382           '';
384         # Ensure the extensions-tool builds.
385         inherit (azure-cli) extensions-tool;
386       };
388       generate-extensions = writeScriptBin "${pname}-update-extensions" ''
389         ${lib.getExe azure-cli.extensions-tool} --cli-version ${azure-cli.version} --commit
390       '';
392       extensions-tool =
393         runCommand "azure-cli-extensions-tool"
394           {
395             src = ./extensions-tool.py;
396             nativeBuildInputs = [
397               black
398               isort
399               makeWrapper
400               mypy
401               python3
402             ];
403             meta.mainProgram = "extensions-tool";
404           }
405           ''
406             black --check --diff $src
407             # mypy --strict $src
408             isort --profile=black --check --diff $src
410             install -Dm755 $src $out/bin/extensions-tool
412             patchShebangs --build $out
413             wrapProgram $out/bin/extensions-tool \
414               --set PYTHONPATH "${
415                 python3.pkgs.makePythonPath (
416                   with python3.pkgs;
417                   [
418                     packaging
419                     semver
420                     gitpython
421                   ]
422                 )
423               }"
424           '';
425     };
427     meta = {
428       homepage = "https://github.com/Azure/azure-cli";
429       description = "Next generation multi-platform command line experience for Azure";
430       downloadPage = "https://github.com/Azure/azure-cli/releases/tag/azure-cli-${version}";
431       longDescription = ''
432         The Azure Command-Line Interface (CLI) is a cross-platform
433         command-line tool to connect to Azure and execute administrative
434         commands on Azure resources. It allows the execution of commands
435         through a terminal using interactive command-line prompts or a script.
437         `azure-cli` has extension support. For example, to install the `aks-preview` extension, use
439         ```nix
440         environment.systemPackages = [
441           (azure-cli.withExtensions [ azure-cli.extensions.aks-preview ])
442         ];
443         ```
445         To make the `azure-cli` immutable and prevent clashes in case `azure-cli` is also installed via other package managers,
446         some configuration files were moved into the derivation. This can be disabled by overriding `withImmutableConfig = false`
447         when building `azure-cli`.
448       '';
449       changelog = "https://github.com/MicrosoftDocs/azure-docs-cli/blob/main/docs-ref-conceptual/release-notes-azure-cli.md";
450       sourceProvenance = [ lib.sourceTypes.fromSource ];
451       license = lib.licenses.mit;
452       mainProgram = "az";
453       maintainers = with lib.maintainers; [ katexochen ] ++ lib.teams.stridtech.members;
454       platforms = lib.platforms.all;
455     };
456   }