From 148202e95e2b11a7306406f1df9e7a64dc6333d7 Mon Sep 17 00:00:00 2001 From: girdharshubham Date: Wed, 14 Aug 2024 18:02:06 +0530 Subject: [PATCH] docs: add docs snip for azure rbac aks api discovery add: License file refactor: general clean up --- .../src/main/resources/reference.conf | 2 +- .../aks}/AzureRbacAksServiceDiscovery.scala | 44 +- .../azureapi/{ => rbac/aks}/JsonFormat.scala | 9 +- .../azureapi/{ => rbac/aks}/PodList.scala | 10 +- .../azureapi/{ => rbac/aks}/Settings.scala | 2 +- discovery-azure-api/src/test/LICENSE | 88 +++ .../AzureRbacAksServiceDiscoveryDocsTest.java | 18 + .../src/test/resources/pods.json | 672 ++++++++++++++++++ .../discovery/azureapi/AzureApiSpec.scala | 11 + .../AzureRbacAksServiceDiscoverySpec.scala | 7 + .../azureapi/rbac/aks/JsonFormatSpec.scala | 66 ++ docs/src/main/paradox/discovery/azure.md | 8 + docs/src/main/paradox/discovery/index.md | 1 + 13 files changed, 903 insertions(+), 35 deletions(-) rename discovery-azure-api/src/main/scala/akka/discovery/azureapi/{ => rbac/aks}/AzureRbacAksServiceDiscovery.scala (90%) rename discovery-azure-api/src/main/scala/akka/discovery/azureapi/{ => rbac/aks}/JsonFormat.scala (75%) rename discovery-azure-api/src/main/scala/akka/discovery/azureapi/{ => rbac/aks}/PodList.scala (73%) rename discovery-azure-api/src/main/scala/akka/discovery/azureapi/{ => rbac/aks}/Settings.scala (98%) create mode 100644 discovery-azure-api/src/test/LICENSE create mode 100644 discovery-azure-api/src/test/java/docs/AzureRbacAksServiceDiscoveryDocsTest.java create mode 100644 discovery-azure-api/src/test/resources/pods.json create mode 100644 discovery-azure-api/src/test/scala/akka/discovery/azureapi/AzureApiSpec.scala create mode 100644 discovery-azure-api/src/test/scala/akka/discovery/azureapi/rbac/aks/AzureRbacAksServiceDiscoverySpec.scala create mode 100644 discovery-azure-api/src/test/scala/akka/discovery/azureapi/rbac/aks/JsonFormatSpec.scala create mode 100644 docs/src/main/paradox/discovery/azure.md diff --git a/discovery-azure-api/src/main/resources/reference.conf b/discovery-azure-api/src/main/resources/reference.conf index 15e218c2..ea24d37f 100644 --- a/discovery-azure-api/src/main/resources/reference.conf +++ b/discovery-azure-api/src/main/resources/reference.conf @@ -6,7 +6,7 @@ akka.discovery { # Set the following in your application.conf if you want to use this discovery mechanism: # method = azure-rbac-aks-api azure-rbac-aks-api { - class = akka.discovery.azureapi.AzureRbacAksServiceDiscovery + class = akka.discovery.azureapi.rbac.aks.AzureRbacAksServiceDiscovery authority-host = "https://login.microsoftonline.com/" authority-host = ${?AZURE_AUTHORITY_HOST} diff --git a/discovery-azure-api/src/main/scala/akka/discovery/azureapi/AzureRbacAksServiceDiscovery.scala b/discovery-azure-api/src/main/scala/akka/discovery/azureapi/rbac/aks/AzureRbacAksServiceDiscovery.scala similarity index 90% rename from discovery-azure-api/src/main/scala/akka/discovery/azureapi/AzureRbacAksServiceDiscovery.scala rename to discovery-azure-api/src/main/scala/akka/discovery/azureapi/rbac/aks/AzureRbacAksServiceDiscovery.scala index ac5408ad..fdfadd18 100644 --- a/discovery-azure-api/src/main/scala/akka/discovery/azureapi/AzureRbacAksServiceDiscovery.scala +++ b/discovery-azure-api/src/main/scala/akka/discovery/azureapi/rbac/aks/AzureRbacAksServiceDiscovery.scala @@ -2,13 +2,13 @@ * Copyright (C) 2017-2024 Lightbend Inc. */ -package akka.discovery.azureapi +package akka.discovery.azureapi.rbac.aks import akka.actor.ExtendedActorSystem import akka.annotation.InternalApi import akka.discovery.ServiceDiscovery.{ Resolved, ResolvedTarget } -import akka.discovery.azureapi.AzureRbacAksServiceDiscovery._ -import akka.discovery.azureapi.JsonFormat._ +import AzureRbacAksServiceDiscovery._ +import JsonFormat._ import akka.discovery.{ Lookup, ServiceDiscovery } import akka.dispatch.Dispatchers.DefaultBlockingDispatcherId import akka.event.Logging @@ -45,7 +45,7 @@ object AzureRbacAksServiceDiscovery { * to do that. */ @InternalApi - private[azureapi] def targets( + private[aks] def targets( podList: PodList, portName: Option[String], podNamespace: String, @@ -99,7 +99,7 @@ class AzureRbacAksServiceDiscovery(implicit system: ExtendedActorSystem) extends log.debug("Settings {}", settings) - private def fetchToken: Future[AccessToken] = + private def fetchAccessToken: Future[AccessToken] = azureDefaultCredential.getToken(accessTokenRequestContext.addScopes(settings.entraServerId)).toFuture.asScala private val kubernetesSetup = { @@ -118,9 +118,9 @@ class AzureRbacAksServiceDiscovery(implicit system: ExtendedActorSystem) extends import system.dispatcher - private def accessToken(retries: Int = 3): Future[AccessToken] = { - fetchToken.flatMap { - case token if token.isExpired && retries > 0 => accessToken(retries - 1) + private def fetchAccessToken(retries: Int = 3): Future[AccessToken] = { + fetchAccessToken.flatMap { + case token if token.isExpired && retries > 0 => fetchAccessToken(retries - 1) case token if token.isExpired => Future.failed(new RuntimeException("Failed to fetch a valid token after multiple attempts")) case token => Future.successful(token) @@ -133,22 +133,18 @@ class AzureRbacAksServiceDiscovery(implicit system: ExtendedActorSystem) extends for { ks <- kubernetesSetup - at <- accessToken() - - request <- { - log.info( - "Querying for pods with label selector: [{}]. Namespace: [{}]. Port: [{}]", - selector, - ks.namespace, - lookup.portName - ) - - optionToFuture( - // FIXME | remove .get - podRequest(at.getToken, ks.namespace, selector), - s"Unable to form request; check Kubernetes environment (expecting env vars ${settings.apiServiceHostEnvName}, ${settings.apiServicePortEnvName})" - ) - } + at <- fetchAccessToken() + + _ = log.info( + "Querying for pods with label selector: [{}]. Namespace: [{}]. Port: [{}]", + selector, + ks.namespace, + lookup.portName) + + request <- optionToFuture( + podRequest(at.getToken, ks.namespace, selector), + s"Unable to form request; check Kubernetes environment (expecting env vars ${settings.apiServiceHostEnvName}, ${settings.apiServicePortEnvName})" + ) response <- http.singleRequest(request, ks.ctx) diff --git a/discovery-azure-api/src/main/scala/akka/discovery/azureapi/JsonFormat.scala b/discovery-azure-api/src/main/scala/akka/discovery/azureapi/rbac/aks/JsonFormat.scala similarity index 75% rename from discovery-azure-api/src/main/scala/akka/discovery/azureapi/JsonFormat.scala rename to discovery-azure-api/src/main/scala/akka/discovery/azureapi/rbac/aks/JsonFormat.scala index 44fdd7a5..0fffa3c3 100644 --- a/discovery-azure-api/src/main/scala/akka/discovery/azureapi/JsonFormat.scala +++ b/discovery-azure-api/src/main/scala/akka/discovery/azureapi/rbac/aks/JsonFormat.scala @@ -2,24 +2,23 @@ * Copyright (C) 2017-2024 Lightbend Inc. */ -package akka.discovery.azureapi +package akka.discovery.azureapi.rbac.aks import akka.annotation.InternalApi -import akka.discovery.azureapi.PodList._ +import PodList._ import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport import spray.json._ /** * INTERNAL API */ -@InternalApi private[azureapi] object JsonFormat extends SprayJsonSupport with DefaultJsonProtocol { - // If adding more formats here, remember to also add in META-INF/native-image reflect config +@InternalApi private[aks] object JsonFormat extends SprayJsonSupport with DefaultJsonProtocol { implicit val containerPortFormat: JsonFormat[ContainerPort] = jsonFormat2(ContainerPort.apply) implicit val containerFormat: JsonFormat[Container] = jsonFormat2(Container.apply) implicit val podSpecFormat: JsonFormat[PodSpec] = jsonFormat1(PodSpec.apply) implicit val containerStatusFormat: JsonFormat[ContainerStatus] = jsonFormat2(ContainerStatus.apply) implicit val podStatusFormat: JsonFormat[PodStatus] = jsonFormat3(PodStatus.apply) - implicit val metadataFormat: JsonFormat[Metadata] = jsonFormat1(Metadata.apply) + implicit val metadataFormat: JsonFormat[Metadata] = jsonFormat2(Metadata.apply) implicit val podFormat: JsonFormat[Pod] = jsonFormat3(Pod.apply) implicit val podListFormat: RootJsonFormat[PodList] = jsonFormat1(PodList.apply) } diff --git a/discovery-azure-api/src/main/scala/akka/discovery/azureapi/PodList.scala b/discovery-azure-api/src/main/scala/akka/discovery/azureapi/rbac/aks/PodList.scala similarity index 73% rename from discovery-azure-api/src/main/scala/akka/discovery/azureapi/PodList.scala rename to discovery-azure-api/src/main/scala/akka/discovery/azureapi/rbac/aks/PodList.scala index e2630561..00232258 100644 --- a/discovery-azure-api/src/main/scala/akka/discovery/azureapi/PodList.scala +++ b/discovery-azure-api/src/main/scala/akka/discovery/azureapi/rbac/aks/PodList.scala @@ -2,7 +2,7 @@ * Copyright (C) 2017-2024 Lightbend Inc. */ -package akka.discovery.azureapi +package akka.discovery.azureapi.rbac.aks import akka.annotation.InternalApi @@ -11,8 +11,9 @@ import scala.collection.immutable /** * INTERNAL API */ -@InternalApi private[azureapi] object PodList { - final case class Metadata(deletionTimestamp: Option[String]) +@InternalApi +private[aks] object PodList { + final case class Metadata(deletionTimestamp: Option[String], labels: Map[String, String] = Map.empty) final case class ContainerPort(name: Option[String], containerPort: Int) @@ -33,4 +34,5 @@ import scala.collection.immutable /** * INTERNAL API */ -@InternalApi private[azureapi] final case class PodList(items: immutable.Seq[PodList.Pod]) +@InternalApi +private[aks] final case class PodList(items: immutable.Seq[PodList.Pod]) diff --git a/discovery-azure-api/src/main/scala/akka/discovery/azureapi/Settings.scala b/discovery-azure-api/src/main/scala/akka/discovery/azureapi/rbac/aks/Settings.scala similarity index 98% rename from discovery-azure-api/src/main/scala/akka/discovery/azureapi/Settings.scala rename to discovery-azure-api/src/main/scala/akka/discovery/azureapi/rbac/aks/Settings.scala index aea01408..eaafa57a 100644 --- a/discovery-azure-api/src/main/scala/akka/discovery/azureapi/Settings.scala +++ b/discovery-azure-api/src/main/scala/akka/discovery/azureapi/rbac/aks/Settings.scala @@ -2,7 +2,7 @@ * Copyright (C) 2017-2024 Lightbend Inc. */ -package akka.discovery.azureapi +package akka.discovery.azureapi.rbac.aks import akka.actor.{ ActorSystem, diff --git a/discovery-azure-api/src/test/LICENSE b/discovery-azure-api/src/test/LICENSE new file mode 100644 index 00000000..49c5a6a8 --- /dev/null +++ b/discovery-azure-api/src/test/LICENSE @@ -0,0 +1,88 @@ +LIGHTBEND COMMERCIAL SOFTWARE LICENSE AGREEMENT + +THIS LIGHTBEND COMMERCIAL SOFTWARE LICENSE AGREEMENT (THIS "AGREEMENT") IS A LEGAL AGREEMENT BETWEEN YOU ("USER") AND LIGHTBEND, INC. ("LICENSOR"). +BY CLICKING THE "I ACCEPT" BUTTON, OR INSTALLING, COPYING OR OTHERWISE USING LIGHTBEND’S SOFTWARE (THE “SOFTWARE”) AND ITS ASSOCIATED USER DOCUMENTATION, USER ACKNOWLEDGES THAT USER HAS REVIEWED AND ACCEPTS THIS AGREEMENT AND AGREES TO BE BOUND BY ALL OF ITS TERMS. +IF YOU ARE AGREEING TO THIS AGREEMENT AS AN INDIVIDUAL, “USER” REFERS TO YOU INDIVIDUALLY. IF YOU ARE AGREEING TO THIS AGREEMENT AS A REPRESENTATIVE OF AN ENTITY, YOU REPRESENT THAT YOU HAVE THE AUTHORITY TO BIND THAT ENTITY AND “USER” REFERS TO THAT ENTITY AND ALL THE USERS ACCESSING THE SOFTWARE BY, THROUGH OR ON BEHALF OF THAT ENTITY. +IF USER DOES NOT AGREE WITH ALL OF THE TERMS OF THIS AGREEMENT, DO NOT INSTALL, COPY OR OTHERWISE USE THE SOFTWARE OR ITS DOCUMENTATION. + +1. DEFINITIONS. + 1. “User System” means User’s website(s), computers, servers and other equipment and software upon and with which the Software is run. + 2. “Documentation” means the user instructions and help files made available by Licensor for use with the Software, as may be updated from time to time by Licensor. + 3. “Intellectual Property Rights” means all intellectual property rights or similar proprietary rights, including + (a) patent rights and utility models, + (b) copyrights and database rights, + (c) trademarks, trade names, domain names and trade dress and the goodwill associated therewith, + (d) trade secrets, + (e) mask works, and + (f) industrial design rights; in each case, including any registrations of, applications to register, and renewals and extensions of, any of the foregoing in any jurisdiction in the world. + 4. “Open Source Software” means all software that is available under the GNU Affero General Public License (AGPL), GNU General Public License (GPL), GNU Lesser General Public License (LGPL), Mozilla Public License (MPL), Apache License, BSD licenses, or any other license that is approved by or similar to those approved by the Open Source Initiative (www.opensource.org). + +2. LICENSES AND RESTRICTIONS. + 1. License. Subject to User’s compliance with the terms and conditions of this Agreement, Licensor hereby grants to User, during the term of this Agreement, a limited, non-exclusive, non-transferable and non-sublicensable right to + (i) install and execute one (1) copy of the Software in accordance with the Documentation, solely in binary form, and not for the benefit of any other person or entity, and + (ii) access and use the Documentation, solely for User’s own internally purposes in support of End User’s permitted use of the Software. + 2. Restrictions. User shall not, directly or indirectly, or permit any User or third party to: + (a) reverse engineer, decompile, disassemble or otherwise attempt to discover the source code or underlying ideas or algorithms of the Software; + (b) modify, translate, or create derivative works based on any element of the Software or any related Documentation (except to the extent applicable laws specifically prohibit such restriction for interoperability purposes, in which case you agree to first contact Licensor and provide Licensor an opportunity to create such changes as are needed for interoperability purposes); + (c) use, rent, lease, distribute, sell, resell, assign, or otherwise transfer the Software or any copy thereof; + (d) use the Software for timesharing purposes or otherwise for the benefit of any person or entity other than for the benefit of User and Users; + (e) remove any proprietary notices from the Software or the Documentation or attempt to defeat any copy protection device included with the Software; or + (f) use the Software for any purpose other than its intended purpose. + 3. Reservation of Rights. Nothing in this Agreement shall be construed to give User a right to use or otherwise obtain access to any source code from which the Software is compiled or interpreted. Except as expressly granted in this Agreement, there are no other licenses granted to User, express, implied or by way of estoppel. All rights not granted in this Agreement are reserved by Licensor. + 4. Open Source Software. Notwithstanding the foregoing, certain items of software included with the Software are Open Source Software and remains subject Open Source Software licenses. Such Open Source Software is not subject to the terms and conditions of this Agreement. +Instead, each such item of Open Source Software is licensed under the terms of the end user license that accompanies such Open Source Software and nothing in this Agreement limits your rights under, or grants you rights that supersede, the terms and conditions of any applicable end user license for such Open Source Software. If required by any license for particular Open Source Software, Licensor makes such Open Source Software, and any Licensor modifications to that Open Source Software, available as further described in the Documentation. +USE OF THE SOFTWARE IN ANY MANNER OTHER THAN AS PROVIDED IN THIS AGREEMENT IS STRICTLY PROHIBITED AND MAY INFRINGE ON THE INTELLECTUAL PROPERTY RIGHTS OF LICENSOR AND/OR ITS LICENSOR(S), SUBJECTING USER TO CIVIL AND CRIMINAL PENALTIES, INCLUDING WITHOUT LIMITATION MONETARY DAMAGES AND IMPRISONMENT FOR COPYRIGHT INFRINGEMENT. + +3. USER OBLIGATIONS. + 1. User System. User is responsible for + (a) obtaining, deploying and maintaining the User System, and all computer hardware, software, modems, routers and other communications equipment necessary for User and its Users to install and use the Software; and + (b) paying all third party fees and access charges incurred in connection with the foregoing. Licensor shall not be responsible for supplying any hardware, software or other equipment to User under this Agreement. + 2. Compliance with Laws. User agrees to use the Software in compliance with all applicable laws, including local laws of the country or region in which User resides, and in compliance with all United States export laws and regulations. User shall not use the Software for any purpose prohibited by applicable law. + 3. Trademarks and Tradenames. With regard to all copies of the Software permitted herein, User shall reproduce on such copies all Licensor copyright notices, and other proprietary notices appearing on and in the original copy of the software received from Licensor. Except as set forth in the foregoing sentence, User will not, during the term of this Agreement or thereafter, use any trademark of Licensor, or any word and/or symbol likely to be confused with any Licensor trademark, either alone or in any combination with other words and/or symbols. + +4. SUPPORT AND MAINTENANCE. + 1. Support. Licensor is not responsible for maintenance or support of the Software, or the equipment on which the Software resides or is used, under this Agreement. By accepting the license granted under this Agreement, User agrees that Licensor will be under no obligation to provide any support, maintenance or service in connection with the Software or such equipment. + 2. Upgrades and Updates. Licensor may from time to time in its sole discretion develop and provide updates for the Software, which may include upgrades, bug fixes, patches, other error corrections, and/or new features (collectively, including related documentation, “Updates”). Updates may also modify or delete in their entirety certain features and functionality. You agree that Licensor has no obligation to provide any Updates or to continue to provide or enable any particular features or functionality. + +5. REPRESENTATIONS AND WARRANTIES; DISCLAIMER. + 1. Mutual Representations and Warranties. Each party represents, warrants and covenants that: + (a) it has the full power and authority to enter into this Agreement and to perform its obligations hereunder, without the need for any consents, approvals or immunities not yet obtained; and + (b) its acceptance of and performance under this Agreement shall not breach any oral or written agreement with any third party or any obligation owed by it to any third party to keep any information or materials in confidence or in trust. + 2. Disclaimer. EXCEPT FOR THE WARRANTIES SET FORTH IN THIS SECTION 5, THE SOFTWARE AND THE DOCUMENTATION ARE PROVIDED ON AN AS-IS BASIS. USER’S USE OF THE SOFTWARE AND THE DOCUMENTATION IS AT USER’S OWN RISK. LICENSOR DOES NOT MAKE, AND HEREBY DISCLAIMS, ANY AND ALL OTHER EXPRESS, STATUTORY AND IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT AND TITLE, QUALITY, SUITABILITY, OPERABILITY, CONDITION, SYSTEM INTEGRATION, NON-INTERFERENCE, WORKMANSHIP, TRUTH, ACCURACY (OF DATA OR ANY OTHER INFORMATION OR CONTENT), ABSENCE OF DEFECTS, WHETHER LATENT OR PATENT, AND ANY WARRANTIES ARISING FROM A COURSE OF DEALING, USAGE, OR TRADE PRACTICE. LICENSOR ALSO DOES NOT WARRANT THAT THE FUNCTIONS CONTAINED IN, PERFORMED AND/OR PROVIDED BY THE SOFTWARE WILL MEET USER’S REQUIREMENTS, THAT THE OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE, THAT THE SOFTWARE WILL BE COMPATIBLE OR WORK WITH ANY THIRD-PARTY SOFTWARE, APPLICATIONS OR DEVICES, OR THAT DEFECTS IN THE SOFTWARE WILL BE CORRECTED. USER EXPRESSLY ACKNOWLEDGES AND AGREES THAT, TO THE EXTENT PERMITTED BY APPLICABLE LAW, ITS USE OF THE SOFTWARE IS AT ITS SOLE RISK AND THAT THE ENTIRE RISK AS TO SATISFACTORY QUALITY, PERFORMANCE, ACCURACY AND EFFORT IS WITH USER. USER FURTHER ACKNOWLEDGES AND AGREES THAT THE SOFTWARE IS NOT INTENDED OR SUITABLE FOR USE IN SITUATIONS OR ENVIRONMENTS WHERE THE FAILURE OR TIME DELAYS OF, OR ERRORS OR INACCURACIES IN THE CONTENT, DATA OR INFORMATION PROVIDED BY THE SOFTWARE COULD LEAD TO DEATH, PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE. ANY WARRANTIES MADE BY LICENSOR ARE FOR THE BENEFIT OF USER ONLY AND NOT FOR THE BENEFIT OF ANY THIRD PARTY. THE SOFTWARE AND THE DOCUMENTATION ARE LICENSED AND NOT SOLD. NO AGENT OF LICENSOR IS AUTHORIZED TO ALTER OR EXPAND THE WARRANTIES OF LICENSOR AS SET FORTH HEREIN. + +6. INDEMNIFICATION. User shall defend Licensor and its licensors and their respective officers, directors and employees (“Licensor Indemnified Parties”) from and against any and all Third-Party Claims which arise out of or relate to: + (a) User’s use or alleged use of the Software other than as permitted under this Agreement; or + (b) arising out of or relating to any violation of Section 2.2, or any violation of applicable laws. User shall pay all damages, costs and expenses, including attorneys’ fees and costs (whether by settlement or award of by a final judicial judgment) incurred by the Licensor Indemnified Parties from any such Third-Party Claim. In no event shall Licensor settle any claim without User’s prior written approval. Licensor may, at its own expense, engage separate counsel to advise Licensor regarding a Third-Party Claim and to participate in the defense of the claim, subject to User’s right to control the defense and settlement. If you are a New Jersey resident, this indemnification clause is to be only as broad and inclusive as is permitted by the law of the state of New Jersey. + +7. CONFIDENTIALITY. + 1. Confidential Information. User acknowledges that the Software contains valuable proprietary information and trade secrets and that unauthorized or improper use of the Software will result in irreparable harm to Licensor for which monetary damages would be inadequate and for which Licensor may be entitled to immediate injunctive relief. Accordingly, you will maintain the confidentiality of the proprietary information and not sell, license, publish, display, distribute, disclose or otherwise make available such proprietary information to any third party, nor use such information except as authorized by this Agreement. + 2. Injunctive Relief. User agrees that any unauthorized disclosure of confidential information may cause immediate and irreparable injury to Licensor and that, in the event of such breach, Licensor will be entitled, in addition to any other available remedies, to seek immediate injunctive and other equitable relief, without bond and without the necessity of showing actual monetary damages. + +8. PROPRIETARY RIGHTS. + 1. Licensor. As between Licensor and User, all right, title and interest in the Software, the Documentation, and any other Licensor materials furnished or made available hereunder, and all modifications and enhancements thereof, and all suggestions, ideas and feedback proposed by User regarding the Software, including all copyright rights, patent rights and other Intellectual Property Rights in each of the foregoing, belong to and are retained solely by Licensor or Licensor’s licensors and providers, as applicable. User hereby does and will irrevocably assign to Licensor all evaluations, ideas, feedback and suggestions made by User to Licensor regarding the Software or the Documentation (collectively, “Feedback”) and all Intellectual Property Rights in the Feedback. + +9. LIMITATION OF LIABILITY. + 1. No Consequential Damages. NEITHER LICENSOR NOR ITS LICENSORS SHALL BE LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL OR PUNITIVE DAMAGES, OR ANY DAMAGES FOR LOST DATA, BUSINESS INTERRUPTION, LOST PROFITS, LOST REVENUE OR LOST BUSINESS, ARISING OUT OF OR IN CONNECTION WITH THIS AGREEMENT, EVEN IF LICENSOR OR ITS LICENSORS OR USER HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, INCLUDING WITHOUT LIMITATION, ANY SUCH DAMAGES ARISING OUT OF THE LICENSING, PROVISION OR USE OF THE SOFTWARE OR THE RESULTS OF THE USE OF THE SOFTWARE. LICENSOR WILL NOT BE LIABLE FOR THE COST OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES. + 2. LIMITS ON LIABILITY. NEITHER LICENSOR NOR ITS LICENSORS SHALL BE LIABLE FOR CUMULATIVE, AGGREGATE DAMAGES GREATER THAN FIVE HUNDRED DOLLARS (US $500). + 3. ESSENTIAL PURPOSE. USER ACKNOWLEDGES THAT THE TERMS IN THIS SECTION 9 (LIMITATION OF LIABILITY) SHALL APPLY TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW AND SHALL APPLY EVEN IF AN EXCLUSIVE OR LIMITED REMEDY STATED HEREIN FAILS OF ITS ESSENTIAL PURPOSE. SOME JURISDICTIONS DO NOT ALLOW CERTAIN LIMITATIONS OF LIABILITY, SO SOME OR ALL OF THE ABOVE LIMITATIONS OF LIABILITY MAY NOT APPLY TO YOU. IF YOU ARE A NEW JERSEY RESIDENT, THIS LIMITATION OF LIABILITY SECTION IS TO BE ONLY AS BROAD AND INCLUSIVE AS IS PERMITTED BY THE LAW OF THE STATE OF NEW JERSEY. + +10. TERM AND TERMINATION. + 1. Term. This Agreement and User’s right to use the Software commences on earlier of the date that User: + (a) installs the Software, + (b) begins using the Software or + (c) otherwise demonstrates assent to this Agreement. + User’s right to use the Software shall continue until such time as this Agreement is terminated (the “Term”). + 2. Termination for Cause. A party may terminate this Agreement, upon written notice to the other party in the event the other party files a petition for bankruptcy or has a petition for bankruptcy filed against it that is not dismissed within sixty (60) calendar days after filing or admits its inability to pay its debts as they mature, makes an assignment for the benefit of its creditors or ceases to function as a going concern or to conduct its operations in the normal course of business and such termination shall occur immediately upon notice. Licensor may terminate this Agreement at any time without notice if it ceases to support the Software, which Licensor may do in its sole discretion. In addition, this Agreement will terminate immediately and automatically without any notice if User breaches any of its terms and conditions. + 3. Termination for Convenience. Either party may terminate this Agreement for convenience on at least thirty (30) calendar days prior written notice to the other party. User may also terminate this Agreement by ceasing all use of the Software. + 4. Effects of Termination. Upon expiration or termination of this Agreement, User’s shall cease all use of the Software and the Documentation and shall destroy all copies of the Software in User’s possession or control. + 5. Survival. This Section and Sections 1, 2.2 (Restrictions), 2.3 (Reservation of Rights), 2.4 (Open Source Software), 5.2 (Disclaimer), 6 (Indemnification), 7 (Confidentiality), 8 (Proprietary Rights), 9 (Limitation of Liability), 10.4 (Effects of Termination) and 11 (Miscellaneous) shall survive any termination or expiration of this Agreement. + +11. MISCELLANEOUS. + 1. Notices. Licensor may give notice to User by means of a general notice through electronic mail to User’s e-mail address, or by written communication sent by first class postage prepaid mail or nationally recognized overnight delivery service to User’s address on record with Licensor. User may give notice to Licensor by written communication sent by first class postage prepaid mail or nationally recognized overnight delivery service addressed to Licensor, Lightbend Inc., 580 California, #1231, San Francisco, CA 94104, Attention: User Support. Notice shall be deemed to have been given upon receipt or, if earlier, two (2) business days after mailing, as applicable. All communications and notices to be made or given pursuant to this Agreement shall be in the English language. + 2. Governing Law. This Agreement and the rights and obligations of the parties to and under this agreement shall be governed by and construed under the laws of the United States and the State of California as applied to agreements entered into and to be performed in such State without giving effect to conflicts of laws rules or principles. The parties agree that the United Nations Convention on Contracts for the International Sale of Goods is specifically excluded from application to this Agreement and that the application of the Uniform Computer Information Transactions Act (UCITA) is specifically disclaimed. Any dispute arising out of or in connection with this Agreement, including but not limited to any question regarding its existence, interpretation, validity, performance, or termination, or any dispute between the parties arising from the parties' relationship created by this Agreement, shall be referred to and finally resolved by arbitration administered by the American Arbitration Association under its rules. The number of arbitrators shall be one (1). The parties shall endeavor to agree upon the sole arbitrator and jointly nominate the arbitrator. If the parties cannot agree upon the sole arbitrator within a time prescribed by AAA, the parties shall request the AAA to propose five (5) arbitrators and each party shall rank the proposed arbitrators. The AAA shall appoint an arbitrator from the list of five (5), based upon the parties' rankings. + 3. U.S. Government Users. If User is a Federal Government entity, Licensor provides the Software and the Documentation, including related software and technology, for ultimate Federal Government end use solely in accordance with the following: Government technical data rights include only those rights customarily provided to the public with a commercial item or process and Government software rights related to the Software and the Documentation include only those rights customarily provided to the public, as defined in this Agreement. The technical data rights and customary commercial software license is provided in accordance with FAR 12.211 (Technical Data) and FAR 12.212 (Software) and, for Department of Defense transactions, DFAR 252.227-7015 (Technical Data – Commercial Items) and DFAR 227.7202-3 (Rights in Commercial Computer Software or Computer Software Documentation). If greater rights are needed, a mutually acceptable written addendum specifically conveying such rights must be included in this Agreement. + 4. Export. The Software utilizes software and technology that may be subject to United States and foreign export controls. User acknowledges and agrees that the Software shall not be used, and none of the underlying information, software, or technology may be transferred or otherwise exported or re-exported to countries as to which the United States maintains an embargo (collectively, “Embargoed Countries”), or to or by a national or resident thereof, or any person or entity on the U.S. Department of Treasury’s List of Specially Designated Nationals or the U.S. Department of Commerce’s Table of Denial Orders (collectively, “Designated Nationals”). The lists of Embargoed Countries and Designated Nationals are subject to change without notice. By using the Software, User represents and warrants that it is not located in, under the control of, or a national or resident of an Embargoed Country or Designated National. The Software may use encryption technology that is subject to licensing requirements under the U.S. Export Administration Regulations, 15 C.F.R. Parts 730-774 and Council Regulation (EC) No. 1334/2000. User agrees to comply strictly with all applicable export laws and assume sole responsibility for obtaining licenses to export or re-export as may be required. Licensor and its licensors make no representation that the Software is appropriate or available for use in other locations. By using the Software, User represents and warrants that it is not located in any such country or on any such list. + 5. General. User shall not assign its rights hereunder, or delegate the performance of any of its duties or obligations hereunder, whether by merger, acquisition, sale of assets, operation of law, or otherwise, without the prior written consent of Licensor. Any purported assignment in violation of the preceding sentence is null and void. Subject to the foregoing, this Agreement shall be binding upon, and inure to the benefit of, the successors and assigns of the parties thereto. Except as otherwise specified in this Agreement, this Agreement may be amended or supplemented only by a writing that refers explicitly to this Agreement and that is signed on behalf of both parties. No waiver will be implied from conduct or failure to enforce rights. No waiver will be effective unless in a writing signed on behalf of the party against whom the waiver is asserted. If any of this Agreement is found invalid or unenforceable that term will be enforced to the maximum extent permitted by law and the remainder of this Agreement will remain in full force. +Nothing contained herein shall be construed as creating an agency, partnership, or other form of joint enterprise between the parties. +This Agreement constitutes the entire agreement between the parties relating to this subject matter and supersedes all prior or simultaneous understandings, representations, discussions, negotiations, and agreements, whether written or oral. +Neither party shall be liable to the other party or any third party for failure or delay in performing its obligations under this Agreement when such failure or delay is due to any cause beyond the control of the party concerned, including, without limitation, force majeure, governmental orders or restrictions, fire, or flood, provided that upon cessation of such events such party shall thereupon promptly perform or complete the performance of its obligations hereunder. \ No newline at end of file diff --git a/discovery-azure-api/src/test/java/docs/AzureRbacAksServiceDiscoveryDocsTest.java b/discovery-azure-api/src/test/java/docs/AzureRbacAksServiceDiscoveryDocsTest.java new file mode 100644 index 00000000..92e3fbd2 --- /dev/null +++ b/discovery-azure-api/src/test/java/docs/AzureRbacAksServiceDiscoveryDocsTest.java @@ -0,0 +1,18 @@ +package docs; + +import akka.actor.ActorSystem; +import akka.discovery.Discovery; +import akka.discovery.ServiceDiscovery; + +/* + AzureRbacAksServiceDiscoveryDocsTest will be used to render docs for azure-rbac-aks-api discovery + on akka.io. + */ +public class AzureRbacAksServiceDiscoveryDocsTest { + public void load() { + ActorSystem system = ActorSystem.create(); + //#azure-rbac-aks-api + ServiceDiscovery discovery = Discovery.get(system).loadServiceDiscovery("azure-rbac-aks-api"); + //#azure-rbac-aks-api + } +} diff --git a/discovery-azure-api/src/test/resources/pods.json b/discovery-azure-api/src/test/resources/pods.json new file mode 100644 index 00000000..fc434560 --- /dev/null +++ b/discovery-azure-api/src/test/resources/pods.json @@ -0,0 +1,672 @@ +{ + "apiVersion": "v1", + "items": [ + { + "apiVersion": "v1", + "kind": "Pod", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/restartedAt": "2024-08-14T17:43:50+05:30" + }, + "creationTimestamp": "2024-08-14T12:58:18Z", + "generateName": "akka-cluster-azure-5c46cccf86-", + "labels": { + "app": "application", + "azure.workload.identity/use": "true" + }, + "name": "akka-cluster-azure-5c46cccf86-54ns8", + "namespace": "test-akka-app", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "akka-cluster-azure-5c46cccf86", + "uid": "f0622dbb-c1a1-48ab-87d2-0db1a361c443" + } + ], + "resourceVersion": "1745735", + "uid": "6b9b5763-806d-4821-9ab1-0341ac2a1548" + }, + "spec": { + "containers": [ + { + "env": [ + { + "name": "AZURE_SERVER_ID", + "value": "6dae42f8-4368-4678-94ff-3960e28e3630/.default" + }, + { + "name": "AZURE_CLIENT_ID", + "value": "cbadab65-1c72-4af6-a096-1147ae6b65d3" + }, + { + "name": "AZURE_TENANT_ID", + "value": "51fafb21-db5e-4294-8268-8c93b235d06d" + }, + { + "name": "AZURE_FEDERATED_TOKEN_FILE", + "value": "/var/run/secrets/azure/tokens/azure-identity-token" + }, + { + "name": "AZURE_AUTHORITY_HOST", + "value": "https://login.microsoftonline.com/" + } + ], + "image": "girdharshubham/akka-cluster-azure", + "imagePullPolicy": "Always", + "name": "akka-cluster-azure", + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "kube-api-access-82kgm", + "readOnly": true + }, + { + "mountPath": "/var/run/secrets/azure/tokens", + "name": "azure-identity-token", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "aks-default-42170094-vmss000000", + "preemptionPolicy": "PreemptLowerPriority", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "test-akka-app", + "serviceAccountName": "test-akka-app", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "kube-api-access-82kgm", + "projected": { + "defaultMode": 420, + "sources": [ + { + "serviceAccountToken": { + "expirationSeconds": 3607, + "path": "token" + } + }, + { + "configMap": { + "items": [ + { + "key": "ca.crt", + "path": "ca.crt" + } + ], + "name": "kube-root-ca.crt" + } + }, + { + "downwardAPI": { + "items": [ + { + "fieldRef": { + "apiVersion": "v1", + "fieldPath": "metadata.namespace" + }, + "path": "namespace" + } + ] + } + } + ] + } + }, + { + "name": "azure-identity-token", + "projected": { + "defaultMode": 420, + "sources": [ + { + "serviceAccountToken": { + "audience": "api://AzureADTokenExchange", + "expirationSeconds": 3600, + "path": "azure-identity-token" + } + } + ] + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2024-08-14T12:58:20Z", + "status": "True", + "type": "PodReadyToStartContainers" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2024-08-14T12:58:18Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2024-08-14T12:58:20Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2024-08-14T12:58:20Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2024-08-14T12:58:18Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "containerd://1b7c99cab1cce7622120f9482af63d1b79447e794191ddf90cd67f06399874e7", + "image": "docker.io/girdharshubham/akka-cluster-azure:latest", + "imageID": "docker.io/girdharshubham/akka-cluster-azure@sha256:361f3868715b3494f3cde263a4a63a8a5ffb7eadf1c4becd60f7c46ac1df635e", + "lastState": {}, + "name": "akka-cluster-azure", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2024-08-14T12:58:19Z" + } + } + } + ], + "hostIP": "10.224.0.4", + "hostIPs": [ + { + "ip": "10.224.0.4" + } + ], + "phase": "Running", + "podIP": "10.244.1.225", + "podIPs": [ + { + "ip": "10.244.1.225" + } + ], + "qosClass": "BestEffort", + "startTime": "2024-08-14T12:58:18Z" + } + }, + { + "apiVersion": "v1", + "kind": "Pod", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/restartedAt": "2024-08-14T17:43:50+05:30" + }, + "creationTimestamp": "2024-08-14T12:58:18Z", + "generateName": "akka-cluster-azure-5c46cccf86-", + "labels": { + "app": "application", + "azure.workload.identity/use": "true" + }, + "name": "akka-cluster-azure-5c46cccf86-74qw2", + "namespace": "test-akka-app", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "akka-cluster-azure-5c46cccf86", + "uid": "f0622dbb-c1a1-48ab-87d2-0db1a361c443" + } + ], + "resourceVersion": "1745733", + "uid": "95e14f4c-c8be-4472-a971-38d1ba3e8377" + }, + "spec": { + "containers": [ + { + "env": [ + { + "name": "AZURE_SERVER_ID", + "value": "6dae42f8-4368-4678-94ff-3960e28e3630/.default" + }, + { + "name": "AZURE_CLIENT_ID", + "value": "cbadab65-1c72-4af6-a096-1147ae6b65d3" + }, + { + "name": "AZURE_TENANT_ID", + "value": "51fafb21-db5e-4294-8268-8c93b235d06d" + }, + { + "name": "AZURE_FEDERATED_TOKEN_FILE", + "value": "/var/run/secrets/azure/tokens/azure-identity-token" + }, + { + "name": "AZURE_AUTHORITY_HOST", + "value": "https://login.microsoftonline.com/" + } + ], + "image": "girdharshubham/akka-cluster-azure", + "imagePullPolicy": "Always", + "name": "akka-cluster-azure", + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "kube-api-access-9jzhf", + "readOnly": true + }, + { + "mountPath": "/var/run/secrets/azure/tokens", + "name": "azure-identity-token", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "aks-default-42170094-vmss000000", + "preemptionPolicy": "PreemptLowerPriority", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "test-akka-app", + "serviceAccountName": "test-akka-app", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "kube-api-access-9jzhf", + "projected": { + "defaultMode": 420, + "sources": [ + { + "serviceAccountToken": { + "expirationSeconds": 3607, + "path": "token" + } + }, + { + "configMap": { + "items": [ + { + "key": "ca.crt", + "path": "ca.crt" + } + ], + "name": "kube-root-ca.crt" + } + }, + { + "downwardAPI": { + "items": [ + { + "fieldRef": { + "apiVersion": "v1", + "fieldPath": "metadata.namespace" + }, + "path": "namespace" + } + ] + } + } + ] + } + }, + { + "name": "azure-identity-token", + "projected": { + "defaultMode": 420, + "sources": [ + { + "serviceAccountToken": { + "audience": "api://AzureADTokenExchange", + "expirationSeconds": 3600, + "path": "azure-identity-token" + } + } + ] + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2024-08-14T12:58:20Z", + "status": "True", + "type": "PodReadyToStartContainers" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2024-08-14T12:58:18Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2024-08-14T12:58:20Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2024-08-14T12:58:20Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2024-08-14T12:58:18Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "containerd://2b99697c2ada28dd91160b448bed2935bc5a0ef33341ad846702444f35ea36c6", + "image": "docker.io/girdharshubham/akka-cluster-azure:latest", + "imageID": "docker.io/girdharshubham/akka-cluster-azure@sha256:361f3868715b3494f3cde263a4a63a8a5ffb7eadf1c4becd60f7c46ac1df635e", + "lastState": {}, + "name": "akka-cluster-azure", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2024-08-14T12:58:19Z" + } + } + } + ], + "hostIP": "10.224.0.4", + "hostIPs": [ + { + "ip": "10.224.0.4" + } + ], + "phase": "Running", + "podIP": "10.244.1.41", + "podIPs": [ + { + "ip": "10.244.1.41" + } + ], + "qosClass": "BestEffort", + "startTime": "2024-08-14T12:58:18Z" + } + }, + { + "apiVersion": "v1", + "kind": "Pod", + "metadata": { + "annotations": { + "kubectl.kubernetes.io/restartedAt": "2024-08-14T17:43:50+05:30" + }, + "creationTimestamp": "2024-08-14T12:58:17Z", + "generateName": "akka-cluster-azure-5c46cccf86-", + "labels": { + "app": "application", + "azure.workload.identity/use": "true" + }, + "name": "akka-cluster-azure-5c46cccf86-shkxx", + "namespace": "test-akka-app", + "ownerReferences": [ + { + "apiVersion": "apps/v1", + "blockOwnerDeletion": true, + "controller": true, + "kind": "ReplicaSet", + "name": "akka-cluster-azure-5c46cccf86", + "uid": "f0622dbb-c1a1-48ab-87d2-0db1a361c443" + } + ], + "resourceVersion": "1745716", + "uid": "44a8f12f-35d2-47a6-a886-adac95f9f82c" + }, + "spec": { + "containers": [ + { + "env": [ + { + "name": "AZURE_SERVER_ID", + "value": "6dae42f8-4368-4678-94ff-3960e28e3630/.default" + }, + { + "name": "AZURE_CLIENT_ID", + "value": "cbadab65-1c72-4af6-a096-1147ae6b65d3" + }, + { + "name": "AZURE_TENANT_ID", + "value": "51fafb21-db5e-4294-8268-8c93b235d06d" + }, + { + "name": "AZURE_FEDERATED_TOKEN_FILE", + "value": "/var/run/secrets/azure/tokens/azure-identity-token" + }, + { + "name": "AZURE_AUTHORITY_HOST", + "value": "https://login.microsoftonline.com/" + } + ], + "image": "girdharshubham/akka-cluster-azure", + "imagePullPolicy": "Always", + "name": "akka-cluster-azure", + "resources": {}, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", + "name": "kube-api-access-sv85p", + "readOnly": true + }, + { + "mountPath": "/var/run/secrets/azure/tokens", + "name": "azure-identity-token", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "enableServiceLinks": true, + "nodeName": "aks-default-42170094-vmss000000", + "preemptionPolicy": "PreemptLowerPriority", + "priority": 0, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "test-akka-app", + "serviceAccountName": "test-akka-app", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "key": "node.kubernetes.io/not-ready", + "operator": "Exists", + "tolerationSeconds": 300 + }, + { + "effect": "NoExecute", + "key": "node.kubernetes.io/unreachable", + "operator": "Exists", + "tolerationSeconds": 300 + } + ], + "volumes": [ + { + "name": "kube-api-access-sv85p", + "projected": { + "defaultMode": 420, + "sources": [ + { + "serviceAccountToken": { + "expirationSeconds": 3607, + "path": "token" + } + }, + { + "configMap": { + "items": [ + { + "key": "ca.crt", + "path": "ca.crt" + } + ], + "name": "kube-root-ca.crt" + } + }, + { + "downwardAPI": { + "items": [ + { + "fieldRef": { + "apiVersion": "v1", + "fieldPath": "metadata.namespace" + }, + "path": "namespace" + } + ] + } + } + ] + } + }, + { + "name": "azure-identity-token", + "projected": { + "defaultMode": 420, + "sources": [ + { + "serviceAccountToken": { + "audience": "api://AzureADTokenExchange", + "expirationSeconds": 3600, + "path": "azure-identity-token" + } + } + ] + } + } + ] + }, + "status": { + "conditions": [ + { + "lastProbeTime": null, + "lastTransitionTime": "2024-08-14T12:58:19Z", + "status": "True", + "type": "PodReadyToStartContainers" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2024-08-14T12:58:17Z", + "status": "True", + "type": "Initialized" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2024-08-14T12:58:19Z", + "status": "True", + "type": "Ready" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2024-08-14T12:58:19Z", + "status": "True", + "type": "ContainersReady" + }, + { + "lastProbeTime": null, + "lastTransitionTime": "2024-08-14T12:58:17Z", + "status": "True", + "type": "PodScheduled" + } + ], + "containerStatuses": [ + { + "containerID": "containerd://c2e4226fb0fd993f26c9fbd8b75b2f87604d8f4549c9bc05af1c02ec1dd52c11", + "image": "docker.io/girdharshubham/akka-cluster-azure:latest", + "imageID": "docker.io/girdharshubham/akka-cluster-azure@sha256:361f3868715b3494f3cde263a4a63a8a5ffb7eadf1c4becd60f7c46ac1df635e", + "lastState": {}, + "name": "akka-cluster-azure", + "ready": true, + "restartCount": 0, + "started": true, + "state": { + "running": { + "startedAt": "2024-08-14T12:58:18Z" + } + } + } + ], + "hostIP": "10.224.0.4", + "hostIPs": [ + { + "ip": "10.224.0.4" + } + ], + "phase": "Running", + "podIP": "10.244.1.221", + "podIPs": [ + { + "ip": "10.244.1.221" + } + ], + "qosClass": "BestEffort", + "startTime": "2024-08-14T12:58:17Z" + } + } + ], + "kind": "List", + "metadata": { + "resourceVersion": "" + } +} \ No newline at end of file diff --git a/discovery-azure-api/src/test/scala/akka/discovery/azureapi/AzureApiSpec.scala b/discovery-azure-api/src/test/scala/akka/discovery/azureapi/AzureApiSpec.scala new file mode 100644 index 00000000..ade60d6e --- /dev/null +++ b/discovery-azure-api/src/test/scala/akka/discovery/azureapi/AzureApiSpec.scala @@ -0,0 +1,11 @@ +package akka.discovery.azureapi + +import org.scalatest.matchers.should.Matchers +import org.scalatest.wordspec.AnyWordSpec + +import scala.io.Source + +class AzureApiSpec extends AnyWordSpec with Matchers { + protected[this] def resourceAsString(name: String): String = + Source.fromInputStream(getClass.getClassLoader.getResourceAsStream(name)).mkString +} diff --git a/discovery-azure-api/src/test/scala/akka/discovery/azureapi/rbac/aks/AzureRbacAksServiceDiscoverySpec.scala b/discovery-azure-api/src/test/scala/akka/discovery/azureapi/rbac/aks/AzureRbacAksServiceDiscoverySpec.scala new file mode 100644 index 00000000..a3c19fac --- /dev/null +++ b/discovery-azure-api/src/test/scala/akka/discovery/azureapi/rbac/aks/AzureRbacAksServiceDiscoverySpec.scala @@ -0,0 +1,7 @@ +package akka.discovery.azureapi.rbac.aks + +import akka.discovery.azureapi.AzureApiSpec + +class AzureRbacAksServiceDiscoverySpec extends AzureApiSpec { + "AzureRbacAksServiceDiscovery" should {} +} diff --git a/discovery-azure-api/src/test/scala/akka/discovery/azureapi/rbac/aks/JsonFormatSpec.scala b/discovery-azure-api/src/test/scala/akka/discovery/azureapi/rbac/aks/JsonFormatSpec.scala new file mode 100644 index 00000000..7a30d505 --- /dev/null +++ b/discovery-azure-api/src/test/scala/akka/discovery/azureapi/rbac/aks/JsonFormatSpec.scala @@ -0,0 +1,66 @@ +package akka.discovery.azureapi.rbac.aks + +import PodList._ +import akka.discovery.azureapi.AzureApiSpec +import spray.json._ + +class JsonFormatSpec extends AzureApiSpec { + "JsonFormat" should { + val pods = resourceAsString("pods.json") + + "work" in { + println(JsonFormat.podListFormat.read(pods.parseJson)) + JsonFormat.podListFormat.read(pods.parseJson) shouldBe PodList( + List( + Pod( + Some(PodSpec(List(Container("akka-cluster-azure", None)))), + Some( + PodStatus( + Some("10.244.1.225"), + Some(List(ContainerStatus("akka-cluster-azure", Map("running" -> ())))), + Some("Running"))), + Some( + Metadata( + deletionTimestamp = None, + Map( + "app" -> "application", + "azure.workload.identity/use" -> "true" + ) + )) + ), + Pod( + Some(PodSpec(List(Container("akka-cluster-azure", None)))), + Some( + PodStatus( + Some("10.244.1.41"), + Some(List(ContainerStatus("akka-cluster-azure", Map("running" -> ())))), + Some("Running"))), + Some( + Metadata( + deletionTimestamp = None, + Map( + "app" -> "application", + "azure.workload.identity/use" -> "true" + ) + )) + ), + Pod( + Some(PodSpec(List(Container("akka-cluster-azure", None)))), + Some( + PodStatus( + Some("10.244.1.221"), + Some(List(ContainerStatus("akka-cluster-azure", Map("running" -> ())))), + Some("Running"))), + Some( + Metadata( + deletionTimestamp = None, + Map( + "app" -> "application", + "azure.workload.identity/use" -> "true" + ) + )) + ) + )) + } + } +} diff --git a/docs/src/main/paradox/discovery/azure.md b/docs/src/main/paradox/discovery/azure.md new file mode 100644 index 00000000..b36f8160 --- /dev/null +++ b/docs/src/main/paradox/discovery/azure.md @@ -0,0 +1,8 @@ +## Azure API + +## Project Info + +@@project-info{ projectId="akka-discovery-azure-api" } + +# Discovery Method: Azure RBAC Based Discovery +You can use Azure RBAC based discovery with Azure workload identity enabled clusters. \ No newline at end of file diff --git a/docs/src/main/paradox/discovery/index.md b/docs/src/main/paradox/discovery/index.md index badfc63b..119d9cb1 100644 --- a/docs/src/main/paradox/discovery/index.md +++ b/docs/src/main/paradox/discovery/index.md @@ -9,6 +9,7 @@ Akka Management contains methods for: * @ref[Kubernetes](kubernetes.md) * @ref[Marathon](marathon.md) * @ref[AWS](aws.md) + * @ref[Azure](azure.md) The @ref[Kubernetes](kubernetes.md) and @extref:[Akka Discovery DNS](akka:discovery/index.html#discovery-method-dns) methods are known to be well used and tested. The others are community contributions that are not tested as