diff --git a/.github/workflows/prs.yml b/.github/workflows/prs.yml index fbe90b1..1096050 100644 --- a/.github/workflows/prs.yml +++ b/.github/workflows/prs.yml @@ -9,7 +9,7 @@ jobs: strategy: matrix: python-version: [3.9, "3.10"] - poetry-version: [1.2.2] + poetry-version: [1.3.2] steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 93b16f1..676cf20 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -13,7 +13,7 @@ jobs: uses: actions/checkout@v3 - name: Build and publish to pypi - uses: JRubics/poetry-publish@v1.13 + uses: JRubics/poetry-publish@v1.16 with: python_version: "3.9" ignore_dev_requirements: "yes" diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b20f61..c5819c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,9 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] +## [0.3.1] - 2023-01-13 -- Add GitHub Action to push package to PyPi +#### Fixed + +- Ensuring `*_ipv4` TaggedAddresses are accounted for. + - Proper casing was adjusted for `address` and `port` TaggedAddress attributes. ## [0.3.0] - 2023-01-13 @@ -34,7 +37,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `timeout` option to the base `ConsulAPI` class to ensure we have a default timeout set but allow it to be overriden. - ## [0.1.0] - 2022-10-24 ### Changed @@ -43,7 +45,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `CONSUL_HTTP_ADDR` - `CONSUL_HTTT_TOKEN` - `CONSUL_NAMESPACE` - - + - ### Added diff --git a/hc_pyconsul/models/health.py b/hc_pyconsul/models/health.py index f73fac7..527fcd5 100644 --- a/hc_pyconsul/models/health.py +++ b/hc_pyconsul/models/health.py @@ -1,3 +1,5 @@ +from typing import Optional + from pydantic import BaseModel from pydantic import Field @@ -24,8 +26,10 @@ class HealthWeights(BaseModel): class NodeTaggedAddresses(BaseModel): - lan: str = Field(..., alias='lan') - wan: str = Field(..., alias='wan') + lan: Optional[str] = Field(None, alias='lan') + lan_ipv4: Optional[str] = Field(None, alias='lan_ipv4') + wan: Optional[str] = Field(None, alias='wan') + wan_ipv4: Optional[str] = Field(None, alias='wan_ipv4') class ServiceNode(BaseModel): @@ -38,13 +42,18 @@ class ServiceNode(BaseModel): class TaggedAddress(BaseModel): - address: str = Field(..., alias='address') - port: int = Field(..., alias='port') + address: str = Field(..., alias='Address') + port: int = Field(..., alias='Port') + + class Config: + allow_population_by_field_name = True class ServiceTaggedAddresses(BaseModel): - lan: TaggedAddress = Field(..., alias='lan') - wan: TaggedAddress = Field(..., alias='wan') + lan: Optional[TaggedAddress] = Field(None, alias='lan') + wan: Optional[TaggedAddress] = Field(None, alias='wan') + lan_ipv4: Optional[TaggedAddress] = Field(None, alias='lan_ipv4') + wan_ipv4: Optional[TaggedAddress] = Field(None, alias='wan_ipv4') class Service(BaseModel): diff --git a/pyproject.toml b/pyproject.toml index 1112ca3..cc1c1e3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "hc_pyconsul" -version = "0.3.0" +version = "0.3.1" description = "API client for HashiCorp Consul" authors = ["Arden Shackelford "] license = "Apache 2.0" diff --git a/tests/fixtures/health/responses.py b/tests/fixtures/health/responses.py index ac60ab4..5c8cb78 100644 --- a/tests/fixtures/health/responses.py +++ b/tests/fixtures/health/responses.py @@ -67,6 +67,77 @@ } ] +LAN_WAN_IPV4_TAGGED_ATTRIBUTES = [ + { + "Node": { + "ID": "40e4a748-2192-161a-0510-9bf59fe950b5", + "Node": "foobar", + "Address": "10.1.10.12", + "Datacenter": "dc1", + "TaggedAddresses": { + "lan_ipv4": "10.1.10.12", + "lan": "10.1.10.12", + "wan": "10.1.10.12", + "wan_ipv4": "10.1.10.12" + }, + "Meta": { + "instance_type": "t2.medium" + } + }, + "Service": { + "ID": "redis", + "Service": "redis", + "Tags": ["primary"], + "Address": "10.1.10.12", + "TaggedAddresses": { + "lan": { + "address": "10.1.10.12", + "port": 8000 + }, + "wan": { + "address": "198.18.1.2", + "port": 80 + } + }, + "Meta": { + "redis_version": "4.0" + }, + "Port": 8000, + "Weights": { + "Passing": 10, + "Warning": 1 + }, + "Namespace": "default" + }, + "Checks": [ + { + "Node": "foobar", + "CheckID": "service:redis", + "Name": "Service 'redis' check", + "Status": "passing", + "Notes": "", + "Output": "", + "ServiceID": "redis", + "ServiceName": "redis", + "ServiceTags": ["primary"], + "Namespace": "default" + }, + { + "Node": "foobar", + "CheckID": "serfHealth", + "Name": "Serf Health Status", + "Status": "passing", + "Notes": "", + "Output": "", + "ServiceID": "", + "ServiceName": "", + "ServiceTags": [], + "Namespace": "default" + } + ] + } +] + SERVICE_LIST_NOMAD = [ { "Node": { diff --git a/tests/test_lib_consul_health.py b/tests/test_lib_consul_health.py index 8ba0e04..2be00bb 100644 --- a/tests/test_lib_consul_health.py +++ b/tests/test_lib_consul_health.py @@ -39,6 +39,16 @@ def test_valid_response(self): self.assertEqual('redis', services[0].service.id) + @respx.mock + def test_valid_response_tagged_addresses(self): + response = respx.get('http://localhost:8500/v1/health/service/foobar') + response.return_value = Response(200, json=responses.LAN_WAN_IPV4_TAGGED_ATTRIBUTES) + + services: list[ServiceHealth] = self.test_health.list_service_instances(service='foobar') + + self.assertEqual('10.1.10.12', services[0].service.tagged_addresses.lan.address) + self.assertEqual('198.18.1.2', services[0].service.tagged_addresses.wan.address) + @respx.mock def test_valid_response_with_nomad_service(self): response = respx.get('http://localhost:8500/v1/health/service/foobar')