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