diff --git a/cli/azd/extensions/azure.coding-agent/CHANGELOG.md b/cli/azd/extensions/azure.coding-agent/CHANGELOG.md index 9aaa6701e27..53dc13d10ec 100644 --- a/cli/azd/extensions/azure.coding-agent/CHANGELOG.md +++ b/cli/azd/extensions/azure.coding-agent/CHANGELOG.md @@ -1,5 +1,12 @@ # Release History +## 0.5.2 + +### Bugs fixed + +- Managed identity creation code was running multiple times, instead of a single time. This should not have broken anything, as the call itself is idempotent but calling it repeatedly is unnecessary. +- `--managed-identity-name`, when specified, now assumes you're creating a credential, eliminating a question from the list. + ## 0.5.1 ### Bugs fixed diff --git a/cli/azd/extensions/azure.coding-agent/extension.yaml b/cli/azd/extensions/azure.coding-agent/extension.yaml index 8c73e4ecbab..462b8fb1b1c 100644 --- a/cli/azd/extensions/azure.coding-agent/extension.yaml +++ b/cli/azd/extensions/azure.coding-agent/extension.yaml @@ -7,4 +7,4 @@ language: go namespace: coding-agent usage: azd coding-agent [options] # NOTE: Make sure version.txt is in sync with this version. -version: 0.5.1 +version: 0.5.2 diff --git a/cli/azd/extensions/azure.coding-agent/go.mod b/cli/azd/extensions/azure.coding-agent/go.mod index ab7b4a05024..933f36a65ca 100644 --- a/cli/azd/extensions/azure.coding-agent/go.mod +++ b/cli/azd/extensions/azure.coding-agent/go.mod @@ -7,14 +7,14 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/msi/armmsi v1.3.0 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0 - github.com/azure/azure-dev/cli/azd v0.0.0 + github.com/azure/azure-dev/cli/azd v0.0.0-20251121174630-055d0cf4cfb4 github.com/cli/browser v1.3.0 github.com/fatih/color v1.18.0 github.com/spf13/cobra v1.10.1 github.com/spf13/pflag v1.0.10 github.com/stretchr/testify v1.11.1 go.uber.org/mock v0.6.0 - google.golang.org/grpc v1.76.0 + google.golang.org/grpc v1.77.0 ) require ( @@ -32,21 +32,23 @@ require ( github.com/blang/semver/v4 v4.0.0 // indirect github.com/braydonk/yaml v0.9.0 // indirect github.com/buger/goterm v1.0.4 // indirect - github.com/charmbracelet/colorprofile v0.3.2 // indirect + github.com/charmbracelet/colorprofile v0.3.3 // indirect github.com/charmbracelet/glamour v0.10.0 // indirect github.com/charmbracelet/lipgloss v1.1.1-0.20250404203927-76690c660834 // indirect - github.com/charmbracelet/x/ansi v0.10.2 // indirect - github.com/charmbracelet/x/cellbuf v0.0.13 // indirect - github.com/charmbracelet/x/exp/slice v0.0.0-20251008171431-5d3777519489 // indirect - github.com/charmbracelet/x/term v0.2.1 // indirect - github.com/clipperhouse/uax29/v2 v2.2.0 // indirect + github.com/charmbracelet/x/ansi v0.11.1 // indirect + github.com/charmbracelet/x/cellbuf v0.0.14 // indirect + github.com/charmbracelet/x/exp/slice v0.0.0-20251118172736-77d017256798 // indirect + github.com/charmbracelet/x/term v0.2.2 // indirect + github.com/clipperhouse/displaywidth v0.6.0 // indirect + github.com/clipperhouse/stringish v0.1.1 // indirect + github.com/clipperhouse/uax29/v2 v2.3.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dlclark/regexp2 v1.11.5 // indirect github.com/drone/envsubst v1.0.3 // indirect github.com/eiannone/keyboard v0.0.0-20220611211555-0d226195f203 // indirect github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/gofrs/flock v0.12.1 // indirect + github.com/gofrs/flock v0.13.0 // indirect github.com/golang-jwt/jwt/v5 v5.3.0 // indirect github.com/golobby/container/v3 v3.3.2 // indirect github.com/google/uuid v1.6.0 // indirect @@ -81,19 +83,17 @@ require ( go.opentelemetry.io/otel/trace v1.38.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.43.0 // indirect - golang.org/x/mod v0.29.0 // indirect - golang.org/x/net v0.46.0 // indirect - golang.org/x/sync v0.17.0 // indirect - golang.org/x/sys v0.37.0 // indirect - golang.org/x/term v0.36.0 // indirect - golang.org/x/text v0.30.0 // indirect - golang.org/x/tools v0.38.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20251007200510-49b9836ed3ff // indirect + golang.org/x/crypto v0.45.0 // indirect + golang.org/x/mod v0.30.0 // indirect + golang.org/x/net v0.47.0 // indirect + golang.org/x/sync v0.18.0 // indirect + golang.org/x/sys v0.38.0 // indirect + golang.org/x/term v0.37.0 // indirect + golang.org/x/text v0.31.0 // indirect + golang.org/x/tools v0.39.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20251111163417-95abcf5c77ba // indirect google.golang.org/protobuf v1.36.10 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) tool go.uber.org/mock/mockgen - -replace github.com/azure/azure-dev/cli/azd => ../.. diff --git a/cli/azd/extensions/azure.coding-agent/go.sum b/cli/azd/extensions/azure.coding-agent/go.sum index 1e97eeab454..ca3e4f3d2ad 100644 --- a/cli/azd/extensions/azure.coding-agent/go.sum +++ b/cli/azd/extensions/azure.coding-agent/go.sum @@ -47,6 +47,8 @@ github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWp github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/azure/azure-dev/cli/azd v0.0.0-20251121174630-055d0cf4cfb4 h1:49slbP1hSOf2x++qOocVbaFBYAJIwI+7AKUzox8jO94= +github.com/azure/azure-dev/cli/azd v0.0.0-20251121174630-055d0cf4cfb4/go.mod h1:k86H7K6vCw8UmimYs0/gDTilxQwXUZDaikRYfDweB/U= github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= @@ -57,26 +59,30 @@ github.com/braydonk/yaml v0.9.0 h1:ewGMrVmEVpsm3VwXQDR388sLg5+aQ8Yihp6/hc4m+h4= github.com/braydonk/yaml v0.9.0/go.mod h1:hcm3h581tudlirk8XEUPDBAimBPbmnL0Y45hCRl47N4= github.com/buger/goterm v1.0.4 h1:Z9YvGmOih81P0FbVtEYTFF6YsSgxSUKEhf/f9bTMXbY= github.com/buger/goterm v1.0.4/go.mod h1:HiFWV3xnkolgrBV3mY8m0X0Pumt4zg4QhbdOzQtB8tE= -github.com/charmbracelet/colorprofile v0.3.2 h1:9J27WdztfJQVAQKX2WOlSSRB+5gaKqqITmrvb1uTIiI= -github.com/charmbracelet/colorprofile v0.3.2/go.mod h1:mTD5XzNeWHj8oqHb+S1bssQb7vIHbepiebQ2kPKVKbI= +github.com/charmbracelet/colorprofile v0.3.3 h1:DjJzJtLP6/NZ8p7Cgjno0CKGr7wwRJGxWUwh2IyhfAI= +github.com/charmbracelet/colorprofile v0.3.3/go.mod h1:nB1FugsAbzq284eJcjfah2nhdSLppN2NqvfotkfRYP4= github.com/charmbracelet/glamour v0.10.0 h1:MtZvfwsYCx8jEPFJm3rIBFIMZUfUJ765oX8V6kXldcY= github.com/charmbracelet/glamour v0.10.0/go.mod h1:f+uf+I/ChNmqo087elLnVdCiVgjSKWuXa/l6NU2ndYk= github.com/charmbracelet/lipgloss v1.1.1-0.20250404203927-76690c660834 h1:ZR7e0ro+SZZiIZD7msJyA+NjkCNNavuiPBLgerbOziE= github.com/charmbracelet/lipgloss v1.1.1-0.20250404203927-76690c660834/go.mod h1:aKC/t2arECF6rNOnaKaVU6y4t4ZeHQzqfxedE/VkVhA= -github.com/charmbracelet/x/ansi v0.10.2 h1:ith2ArZS0CJG30cIUfID1LXN7ZFXRCww6RUvAPA+Pzw= -github.com/charmbracelet/x/ansi v0.10.2/go.mod h1:HbLdJjQH4UH4AqA2HpRWuWNluRE6zxJH/yteYEYCFa8= -github.com/charmbracelet/x/cellbuf v0.0.13 h1:/KBBKHuVRbq1lYx5BzEHBAFBP8VcQzJejZ/IA3iR28k= -github.com/charmbracelet/x/cellbuf v0.0.13/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs= +github.com/charmbracelet/x/ansi v0.11.1 h1:iXAC8SyMQDJgtcz9Jnw+HU8WMEctHzoTAETIeA3JXMk= +github.com/charmbracelet/x/ansi v0.11.1/go.mod h1:M49wjzpIujwPceJ+t5w3qh2i87+HRtHohgb5iTyepL0= +github.com/charmbracelet/x/cellbuf v0.0.14 h1:iUEMryGyFTelKW3THW4+FfPgi4fkmKnnaLOXuc+/Kj4= +github.com/charmbracelet/x/cellbuf v0.0.14/go.mod h1:P447lJl49ywBbil/KjCk2HexGh4tEY9LH0/1QrZZ9rA= github.com/charmbracelet/x/exp/golden v0.0.0-20240806155701-69247e0abc2a h1:G99klV19u0QnhiizODirwVksQB91TJKV/UaTnACcG30= github.com/charmbracelet/x/exp/golden v0.0.0-20240806155701-69247e0abc2a/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= -github.com/charmbracelet/x/exp/slice v0.0.0-20251008171431-5d3777519489 h1:a5q2sWiet6kgqucSGjYN1jhT2cn4bMKUwprtm2IGRto= -github.com/charmbracelet/x/exp/slice v0.0.0-20251008171431-5d3777519489/go.mod h1:vqEfX6xzqW1pKKZUUiFOKg0OQ7bCh54Q2vR/tserrRA= -github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ= -github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= +github.com/charmbracelet/x/exp/slice v0.0.0-20251118172736-77d017256798 h1:EkOQR1G3MhyPxA39njT7E33V1Y/bDbF1XxEcMmM6Ox8= +github.com/charmbracelet/x/exp/slice v0.0.0-20251118172736-77d017256798/go.mod h1:vqEfX6xzqW1pKKZUUiFOKg0OQ7bCh54Q2vR/tserrRA= +github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk= +github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI= github.com/cli/browser v1.3.0 h1:LejqCrpWr+1pRqmEPDGnTZOjsMe7sehifLynZJuqJpo= github.com/cli/browser v1.3.0/go.mod h1:HH8s+fOAxjhQoBUAsKuPCbqUuxZDhQ2/aD+SzsEfBTk= -github.com/clipperhouse/uax29/v2 v2.2.0 h1:ChwIKnQN3kcZteTXMgb1wztSgaU+ZemkgWdohwgs8tY= -github.com/clipperhouse/uax29/v2 v2.2.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM= +github.com/clipperhouse/displaywidth v0.6.0 h1:k32vueaksef9WIKCNcoqRNyKbyvkvkysNYnAWz2fN4s= +github.com/clipperhouse/displaywidth v0.6.0/go.mod h1:R+kHuzaYWFkTm7xoMmK1lFydbci4X2CicfbGstSGg0o= +github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs= +github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA= +github.com/clipperhouse/uax29/v2 v2.3.0 h1:SNdx9DVUqMoBuBoW3iLOj4FQv3dN5mDtuqwuhIGpJy4= +github.com/clipperhouse/uax29/v2 v2.3.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/creack/pty v1.1.17 h1:QeVUsEDNrLBW4tMgZHvxy18sKtr6VI492kBhUfhDJNI= github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= @@ -98,8 +104,8 @@ github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E= -github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0= +github.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw= +github.com/gofrs/flock v0.13.0/go.mod h1:jxeyy9R1auM5S6JYDBhDt+E2TCo7DkratH4Pgi8P+Z0= github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= @@ -227,24 +233,24 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= -golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= +golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= +golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= golang.org/x/exp v0.0.0-20250911091902-df9299821621 h1:2id6c1/gto0kaHYyrixvknJ8tUK/Qs5IsmBtrc+FtgU= golang.org/x/exp v0.0.0-20250911091902-df9299821621/go.mod h1:TwQYMMnGpvZyc+JpB/UAuTNIsVJifOlSkrZkhcvpVUk= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA= -golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w= +golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk= +golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4= -golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= +golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= +golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= -golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= +golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -256,30 +262,30 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= -golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q= -golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss= +golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= +golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= -golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= +golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= +golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ= -golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs= +golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ= +golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251007200510-49b9836ed3ff h1:A90eA31Wq6HOMIQlLfzFwzqGKBTuaVztYu/g8sn+8Zc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251007200510-49b9836ed3ff/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= -google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A= -google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251111163417-95abcf5c77ba h1:UKgtfRM7Yh93Sya0Fo8ZzhDP4qBckrrxEr2oF5UIVb8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251111163417-95abcf5c77ba/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= +google.golang.org/grpc v1.77.0 h1:wVVY6/8cGA6vvffn+wWK5ToddbgdU3d8MNENr4evgXM= +google.golang.org/grpc v1.77.0/go.mod h1:z0BY1iVj0q8E1uSQCjL9cppRj+gnZjzDnzV0dHhrNig= google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/cli/azd/extensions/azure.coding-agent/internal/cmd/coding_agent_config.go b/cli/azd/extensions/azure.coding-agent/internal/cmd/coding_agent_config.go index 4eeab7d312b..6e5704101d1 100644 --- a/cli/azd/extensions/azure.coding-agent/internal/cmd/coding_agent_config.go +++ b/cli/azd/extensions/azure.coding-agent/internal/cmd/coding_agent_config.go @@ -50,6 +50,7 @@ var prBodyMD string const copilotEnv = "copilot" const readmeURL = "https://github.com/Azure/azure-dev/blob/main/cli/azd/extensions/azure.coding-agent/README.md" +const defaultManagedIdentityName = "mi-copilot-coding-agent" type flagValues struct { Debug bool @@ -89,7 +90,7 @@ func setupFlags(commandFlags *pflag.FlagSet) *flagValues { commandFlags.StringVar( &flagValues.ManagedIdentityName, "managed-identity-name", - "mi-copilot-coding-agent", + defaultManagedIdentityName, "The name to use for the managed identity, if created.", ) @@ -523,30 +524,39 @@ func pickOrCreateMSI(ctx context.Context, // ************************** Pick or create a new MSI ************************** - // Prompt for pick or create a new MSI - selectedOption, err := prompter.Select(ctx, &azdext.SelectRequest{ - Options: &azdext.SelectOptions{ - Message: "Do you want to create a new Azure user-assigned managed identity or use an existing one?", - Choices: []*azdext.SelectChoice{ - {Label: "Create new user-assigned managed identity"}, - {Label: "Use existing user-assigned managed identity"}, + shouldCreateIdentity := true + + if identityName == defaultManagedIdentityName { + // Prompt for pick or create a new MSI + selectedOption, err := prompter.Select(ctx, &azdext.SelectRequest{ + Options: &azdext.SelectOptions{ + Message: "Do you want to create a new Azure user-assigned managed identity or use an existing one?", + Choices: []*azdext.SelectChoice{ + {Label: "Create new user-assigned managed identity"}, + {Label: "Use existing user-assigned managed identity"}, + }, + HelpMessage: "", }, - HelpMessage: "", - }, - }) - if err != nil { - //nolint:lll - return nil, fmt.Errorf( - "failed when prompting for managed identity option. Try logging in manually with 'azd auth login' before running this command. Error: %w", - err, - ) + }) + + if err != nil { + //nolint:lll + return nil, fmt.Errorf( + "failed when prompting for managed identity option. Try logging in manually with 'azd auth login' before running this command. Error: %w", + err, + ) + } + + shouldCreateIdentity = *selectedOption.Value == 0 } taskList := ux.NewTaskList(nil) + // this gets assigned when the task list runs - it's either a brand new identity, or an + // existing identity. var managedIdentity rm_armmsi.Identity - if *selectedOption.Value == 0 { + if shouldCreateIdentity { // pick a resource group and location for the new MSI location, err := prompter.PromptLocation(ctx, &azdext.PromptLocationRequest{ AzureContext: &azdext.AzureContext{ @@ -646,21 +656,23 @@ func pickOrCreateMSI(ctx context.Context, managedIdentity = msIdentities[*selectedOption.Value] } - if err := taskList.Run(); err != nil { - return nil, err - } - roleNameStrings := strings.Join(roleNames, ", ") - parsedID, err := arm.ParseResourceID(*managedIdentity.ID) - - if err != nil { - return nil, fmt.Errorf("invalid format for managed identity resource id: %w", err) - } + var resourceGroup string // filled out when we ensure role assignments taskList.AddTask(ux.TaskOptions{ Title: fmt.Sprintf("Assigning roles (%s) to User Managed Identity (MSI)", roleNameStrings), Action: func(spf ux.SetProgressFunc) (ux.TaskState, error) { - err := entraIDService.EnsureRoleAssignments( + // managedIdentity is filled out by an earlier step in this task list + // or chosen by the user when they say "use existing" + parsedID, err := arm.ParseResourceID(*managedIdentity.ID) + + if err != nil { + return ux.Error, fmt.Errorf("invalid format for managed identity resource id: %w", err) + } + + resourceGroup = parsedID.ResourceGroupName + + err = entraIDService.EnsureRoleAssignments( ctx, subscriptionId, roleNames, @@ -687,7 +699,7 @@ func pickOrCreateMSI(ctx context.Context, return &authConfiguration{ Name: *managedIdentity.Name, - ResourceGroup: parsedID.ResourceGroupName, + ResourceGroup: resourceGroup, TenantId: *managedIdentity.Properties.TenantID, SubscriptionId: subscriptionId, ResourceID: *managedIdentity.ID, diff --git a/cli/azd/extensions/azure.coding-agent/internal/cmd/coding_agent_config_test.go b/cli/azd/extensions/azure.coding-agent/internal/cmd/coding_agent_config_test.go index ea6133dc856..c8edce23eeb 100644 --- a/cli/azd/extensions/azure.coding-agent/internal/cmd/coding_agent_config_test.go +++ b/cli/azd/extensions/azure.coding-agent/internal/cmd/coding_agent_config_test.go @@ -5,12 +5,15 @@ package cmd import ( "context" + "fmt" "testing" "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" azure_armmsi "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/msi/armmsi" + rm_armmsi "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/msi/armmsi" "github.com/azure/azure-dev/cli/azd/pkg/azdext" exec "github.com/azure/azure-dev/cli/azd/pkg/exec" + "github.com/azure/azure-dev/cli/azd/pkg/graphsdk" "github.com/azure/azure-dev/cli/azd/pkg/input" azd_github "github.com/azure/azure-dev/cli/azd/pkg/tools/github" "github.com/stretchr/testify/require" @@ -21,6 +24,8 @@ import ( //go:generate go tool mockgen -destination mocks_azdext_test.go -copyright_file ./testdata/mock_copyright.txt -package cmd github.com/azure/azure-dev/cli/azd/pkg/azdext PromptServiceClient +//go:generate go tool mockgen -destination mocks_azd_entraid.go -copyright_file ./testdata/mock_copyright.txt -package cmd github.com/azure/azure-dev/cli/azd/pkg/entraid EntraIdService + //go:generate go tool mockgen -destination mocks_azdexec_test.go -copyright_file ./testdata/mock_copyright.txt -package cmd github.com/azure/azure-dev/cli/azd/pkg/exec CommandRunner //go:generate go tool mockgen -destination mocks_azdinput_test.go -copyright_file ./testdata/mock_copyright.txt -package cmd github.com/azure/azure-dev/cli/azd/pkg/input Console @@ -171,6 +176,185 @@ func TestCodingAgent_loginToGitHubIfNeeded(t *testing.T) { }) } +func TestCodingAgent_pickOrCreateMSI(t *testing.T) { + const fakeSubscriptionID = "fake-subscription-id" + const fakeResourceGroup = "fake-resource-group" + const fakeLocation = "fake-location" + const fakeTenantID = "tenant-id" + const fakeClientID = "client-id" + + setup := func(t *testing.T) (*MockPromptServiceClient, *MockazdMSIService, *MockEntraIdService, *MockresourceService) { + ctrl := gomock.NewController(t) + promptService := NewMockPromptServiceClient(ctrl) + msiService := NewMockazdMSIService(ctrl) + entraService := NewMockEntraIdService(ctrl) + resourceService := NewMockresourceService(ctrl) + + promptService.EXPECT(). + PromptLocation(gomock.Any(), gomock.Any()). + Return(&azdext.PromptLocationResponse{ + Location: &azdext.Location{ + Name: fakeLocation, + }, + }, nil). + AnyTimes() + + promptService.EXPECT(). + PromptResourceGroup(gomock.Any(), gomock.Any()). + Return(&azdext.PromptResourceGroupResponse{ + ResourceGroup: &azdext.ResourceGroup{ + Name: fakeResourceGroup, + }, + }, nil). + AnyTimes() + + return promptService, msiService, entraService, resourceService + } + + t.Run("UsingDefaultIdentity_createNewIdentity", func(t *testing.T) { + // the simplest "create" flow - they're going to create a new identity, using all the defaults. + promptService, msiService, entraService, resourceService := setup(t) + + promptService.EXPECT().Select(gomock.Any(), + SelectMatcher{T: t, ExpectedQuestion: "Do you want to create a new Azure user-assigned managed identity or use an existing one?"}). + Return(&azdext.SelectResponse{ + Value: to.Ptr(int32(0)), // ie, "create a new one" + }, nil) + + msiService.EXPECT(). + CreateUserIdentity(gomock.Any(), fakeSubscriptionID, fakeResourceGroup, fakeLocation, defaultManagedIdentityName). + Return(azure_armmsi.Identity{ + Properties: &azure_armmsi.UserAssignedIdentityProperties{ + PrincipalID: to.Ptr("principal-id"), + ClientID: to.Ptr(fakeClientID), + TenantID: to.Ptr(fakeTenantID), + }, + Name: to.Ptr(string(defaultManagedIdentityName)), + ID: to.Ptr(fmt.Sprintf("/subscriptions/%s/resourcegroups/%s/providers/Microsoft.ManagedIdentity/userAssignedIdentities/%s", fakeSubscriptionID, fakeResourceGroup, defaultManagedIdentityName)), + }, nil) + + entraService.EXPECT().EnsureRoleAssignments(gomock.Any(), + fakeSubscriptionID, + []string{"Reader"}, + &graphsdk.ServicePrincipal{ + Id: to.Ptr("principal-id"), + DisplayName: defaultManagedIdentityName, + }, gomock.Any()). + Return(nil) + + authConfig, err := pickOrCreateMSI(context.Background(), + promptService, + msiService, + entraService, + resourceService, + defaultManagedIdentityName, + fakeSubscriptionID, + []string{"Reader"}) + require.NoError(t, err) + + require.Equal(t, fakeClientID, authConfig.ClientId) + require.Equal(t, defaultManagedIdentityName, authConfig.Name) + require.Equal(t, fakeTenantID, authConfig.TenantId) + require.Equal(t, fakeResourceGroup, authConfig.ResourceGroup) + }) + + t.Run("UsingCustomManagedIdentityNameAndRoles_assumesCreate", func(t *testing.T) { + // similar to the create flow above, except that specifying a custom name for the identity + // automaticaly chooses the "create" path. + promptService, msiService, entraService, resourceService := setup(t) + const customManagedIdentityName = "identity-name" + + msiService.EXPECT(). + CreateUserIdentity(gomock.Any(), fakeSubscriptionID, fakeResourceGroup, fakeLocation, customManagedIdentityName). + Return(azure_armmsi.Identity{ + Properties: &azure_armmsi.UserAssignedIdentityProperties{ + PrincipalID: to.Ptr("principal-id"), + ClientID: to.Ptr(fakeClientID), + TenantID: to.Ptr(fakeTenantID), + }, + Name: to.Ptr(customManagedIdentityName), + ID: to.Ptr(fmt.Sprintf("/subscriptions/%s/resourcegroups/%s/providers/Microsoft.ManagedIdentity/userAssignedIdentities/%s", fakeSubscriptionID, fakeResourceGroup, customManagedIdentityName)), + }, nil) + + entraService.EXPECT().EnsureRoleAssignments(gomock.Any(), fakeSubscriptionID, []string{"custom-role-name"}, &graphsdk.ServicePrincipal{ + Id: to.Ptr("principal-id"), + DisplayName: customManagedIdentityName, + }, gomock.Any()). + Return(nil) + + authConfig, err := pickOrCreateMSI(context.Background(), + promptService, + msiService, + entraService, + resourceService, + customManagedIdentityName, + fakeSubscriptionID, + []string{"custom-role-name"}) + require.NoError(t, err) + + require.Equal(t, fakeClientID, authConfig.ClientId) + require.Equal(t, customManagedIdentityName, authConfig.Name) + require.Equal(t, fakeTenantID, authConfig.TenantId) + require.Equal(t, fakeResourceGroup, authConfig.ResourceGroup) + }) + + t.Run("UsingDefaultIdentity_useExisting", func(t *testing.T) { + // uses an existing identity - no identity should be created! + promptService, msiService, entraService, resourceService := setup(t) + + promptService.EXPECT().Select(gomock.Any(), + SelectMatcher{T: t, ExpectedQuestion: "Do you want to create a new Azure user-assigned managed identity or use an existing one?"}). + Return(&azdext.SelectResponse{ + Value: to.Ptr(int32(1)), // ie, "use an existing one" + }, nil) + + msiService.EXPECT(). + ListUserIdentities(gomock.Any(), fakeSubscriptionID). + Return([]rm_armmsi.Identity{ + { + Properties: &azure_armmsi.UserAssignedIdentityProperties{ + PrincipalID: to.Ptr("principal-id"), + ClientID: to.Ptr(fakeClientID), + TenantID: to.Ptr(fakeTenantID), + }, + Name: to.Ptr(string(defaultManagedIdentityName)), + ID: to.Ptr(fmt.Sprintf("/subscriptions/%s/resourcegroups/%s/providers/Microsoft.ManagedIdentity/userAssignedIdentities/%s", fakeSubscriptionID, fakeResourceGroup, defaultManagedIdentityName)), + Location: to.Ptr(fakeLocation), + }, + }, nil) + + promptService.EXPECT(). + Select(gomock.Any(), SelectMatcher{T: t, ExpectedQuestion: "Select an existing User Managed Identity (MSI) to use"}). + Return(&azdext.SelectResponse{ + Value: to.Ptr(int32(0)), // pick the first ID in the list (also, the only ID I returned) + }, nil) + + entraService.EXPECT().EnsureRoleAssignments(gomock.Any(), + fakeSubscriptionID, + []string{"Reader"}, + &graphsdk.ServicePrincipal{ + Id: to.Ptr("principal-id"), + DisplayName: defaultManagedIdentityName, + }, gomock.Any()). + Return(nil) + + authConfig, err := pickOrCreateMSI(context.Background(), + promptService, + msiService, + entraService, + resourceService, + defaultManagedIdentityName, + fakeSubscriptionID, + []string{"Reader"}) + require.NoError(t, err) + + require.Equal(t, fakeClientID, authConfig.ClientId) + require.Equal(t, defaultManagedIdentityName, authConfig.Name) + require.Equal(t, fakeTenantID, authConfig.TenantId) + require.Equal(t, fakeResourceGroup, authConfig.ResourceGroup) + }) +} + type FedCredentialMatcher struct { T *testing.T Expected azure_armmsi.FederatedIdentityCredential @@ -197,3 +381,18 @@ func (m GitHubEnvMatcher) Matches(x any) bool { // String describes what the matcher matches. func (m GitHubEnvMatcher) String() string { return "Checks copilot env was specified" } + +type SelectMatcher struct { + T *testing.T + ExpectedQuestion string +} + +func (m SelectMatcher) Matches(x any) bool { + req := x.(*azdext.SelectRequest) + require.Equal(m.T, m.ExpectedQuestion, req.Options.Message) + return true +} + +func (m SelectMatcher) String() string { + return "Checks that the select prompt was the one we're expecting" +} diff --git a/cli/azd/extensions/azure.coding-agent/internal/cmd/mocks_azd_entraid.go b/cli/azd/extensions/azure.coding-agent/internal/cmd/mocks_azd_entraid.go new file mode 100644 index 00000000000..e5aaa6a66b3 --- /dev/null +++ b/cli/azd/extensions/azure.coding-agent/internal/cmd/mocks_azd_entraid.go @@ -0,0 +1,135 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. +// + +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/azure/azure-dev/cli/azd/pkg/entraid (interfaces: EntraIdService) +// +// Generated by this command: +// +// mockgen -destination mocks_azd_entraid.go -copyright_file ./testdata/mock_copyright.txt -package cmd github.com/azure/azure-dev/cli/azd/pkg/entraid EntraIdService +// + +// Package cmd is a generated GoMock package. +package cmd + +import ( + context "context" + reflect "reflect" + + entraid "github.com/azure/azure-dev/cli/azd/pkg/entraid" + graphsdk "github.com/azure/azure-dev/cli/azd/pkg/graphsdk" + gomock "go.uber.org/mock/gomock" +) + +// MockEntraIdService is a mock of EntraIdService interface. +type MockEntraIdService struct { + ctrl *gomock.Controller + recorder *MockEntraIdServiceMockRecorder + isgomock struct{} +} + +// MockEntraIdServiceMockRecorder is the mock recorder for MockEntraIdService. +type MockEntraIdServiceMockRecorder struct { + mock *MockEntraIdService +} + +// NewMockEntraIdService creates a new mock instance. +func NewMockEntraIdService(ctrl *gomock.Controller) *MockEntraIdService { + mock := &MockEntraIdService{ctrl: ctrl} + mock.recorder = &MockEntraIdServiceMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockEntraIdService) EXPECT() *MockEntraIdServiceMockRecorder { + return m.recorder +} + +// ApplyFederatedCredentials mocks base method. +func (m *MockEntraIdService) ApplyFederatedCredentials(ctx context.Context, subscriptionId, clientId string, federatedCredentials []*graphsdk.FederatedIdentityCredential) ([]*graphsdk.FederatedIdentityCredential, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ApplyFederatedCredentials", ctx, subscriptionId, clientId, federatedCredentials) + ret0, _ := ret[0].([]*graphsdk.FederatedIdentityCredential) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ApplyFederatedCredentials indicates an expected call of ApplyFederatedCredentials. +func (mr *MockEntraIdServiceMockRecorder) ApplyFederatedCredentials(ctx, subscriptionId, clientId, federatedCredentials any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ApplyFederatedCredentials", reflect.TypeOf((*MockEntraIdService)(nil).ApplyFederatedCredentials), ctx, subscriptionId, clientId, federatedCredentials) +} + +// CreateOrUpdateServicePrincipal mocks base method. +func (m *MockEntraIdService) CreateOrUpdateServicePrincipal(ctx context.Context, subscriptionId, appIdOrName string, options entraid.CreateOrUpdateServicePrincipalOptions) (*graphsdk.ServicePrincipal, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CreateOrUpdateServicePrincipal", ctx, subscriptionId, appIdOrName, options) + ret0, _ := ret[0].(*graphsdk.ServicePrincipal) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CreateOrUpdateServicePrincipal indicates an expected call of CreateOrUpdateServicePrincipal. +func (mr *MockEntraIdServiceMockRecorder) CreateOrUpdateServicePrincipal(ctx, subscriptionId, appIdOrName, options any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateOrUpdateServicePrincipal", reflect.TypeOf((*MockEntraIdService)(nil).CreateOrUpdateServicePrincipal), ctx, subscriptionId, appIdOrName, options) +} + +// CreateRbac mocks base method. +func (m *MockEntraIdService) CreateRbac(ctx context.Context, subscriptionId, scope, roleId, principalId string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CreateRbac", ctx, subscriptionId, scope, roleId, principalId) + ret0, _ := ret[0].(error) + return ret0 +} + +// CreateRbac indicates an expected call of CreateRbac. +func (mr *MockEntraIdServiceMockRecorder) CreateRbac(ctx, subscriptionId, scope, roleId, principalId any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateRbac", reflect.TypeOf((*MockEntraIdService)(nil).CreateRbac), ctx, subscriptionId, scope, roleId, principalId) +} + +// EnsureRoleAssignments mocks base method. +func (m *MockEntraIdService) EnsureRoleAssignments(ctx context.Context, subscriptionId string, roleNames []string, servicePrincipal *graphsdk.ServicePrincipal, options *entraid.EnsureRoleAssignmentsOptions) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "EnsureRoleAssignments", ctx, subscriptionId, roleNames, servicePrincipal, options) + ret0, _ := ret[0].(error) + return ret0 +} + +// EnsureRoleAssignments indicates an expected call of EnsureRoleAssignments. +func (mr *MockEntraIdServiceMockRecorder) EnsureRoleAssignments(ctx, subscriptionId, roleNames, servicePrincipal, options any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EnsureRoleAssignments", reflect.TypeOf((*MockEntraIdService)(nil).EnsureRoleAssignments), ctx, subscriptionId, roleNames, servicePrincipal, options) +} + +// GetServicePrincipal mocks base method. +func (m *MockEntraIdService) GetServicePrincipal(ctx context.Context, subscriptionId, appIdOrName string) (*graphsdk.ServicePrincipal, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetServicePrincipal", ctx, subscriptionId, appIdOrName) + ret0, _ := ret[0].(*graphsdk.ServicePrincipal) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetServicePrincipal indicates an expected call of GetServicePrincipal. +func (mr *MockEntraIdServiceMockRecorder) GetServicePrincipal(ctx, subscriptionId, appIdOrName any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetServicePrincipal", reflect.TypeOf((*MockEntraIdService)(nil).GetServicePrincipal), ctx, subscriptionId, appIdOrName) +} + +// ResetPasswordCredentials mocks base method. +func (m *MockEntraIdService) ResetPasswordCredentials(ctx context.Context, subscriptionId, appId string) (*entraid.AzureCredentials, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ResetPasswordCredentials", ctx, subscriptionId, appId) + ret0, _ := ret[0].(*entraid.AzureCredentials) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ResetPasswordCredentials indicates an expected call of ResetPasswordCredentials. +func (mr *MockEntraIdServiceMockRecorder) ResetPasswordCredentials(ctx, subscriptionId, appId any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResetPasswordCredentials", reflect.TypeOf((*MockEntraIdService)(nil).ResetPasswordCredentials), ctx, subscriptionId, appId) +} diff --git a/cli/azd/extensions/azure.coding-agent/version.txt b/cli/azd/extensions/azure.coding-agent/version.txt index 4b9fcbec101..cb0c939a936 100644 --- a/cli/azd/extensions/azure.coding-agent/version.txt +++ b/cli/azd/extensions/azure.coding-agent/version.txt @@ -1 +1 @@ -0.5.1 +0.5.2