Skip to content

Commit

Permalink
Merge pull request #1 from ba-st/api-integration
Browse files Browse the repository at this point in the history
Integration with Consul HTTP API
  • Loading branch information
gcotelli authored Jan 31, 2020
2 parents 2aa4717 + 1567bdc commit 151f7ca
Show file tree
Hide file tree
Showing 19 changed files with 1,231 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
[![Pharo 8.0](https://img.shields.io/badge/Pharo-8.0-informational)](https://pharo.org)


The integration provided in the operational plugin interacts with Consult HTTP API to register and deregister the configured services when the API starts/stops.
The integration provided in the operational plugin interacts with Consul HTTP API to register and deregister the configured services when the API starts/stops.

## License

Expand Down
30 changes: 30 additions & 0 deletions docs/ServiceDiscovery.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Consul Service Discovery

One of the operational plugins. When enabled interacts with the [Consul Agent HTTP API](https://www.consul.io/api/index.html) to register the running service when the API starts and to deregister it when the API shuts down.

This plugin is disabled by default and allows configuring the services to register. This configuration is made via the `#operations` config.

For example:

```smalltalk
Dictionary new
at: #operations put: (
Dictionary new
at: 'consul-service-discovery'
put: {
#enabled -> true.
#consulAgentLocation -> 'http://localhost:8500' asUrl.
#definitions -> (Array with: self serviceDefinition)
} asDictionary;
yourself
);
yourself
```

To create service definitions you can use `ConsulServiceDefinitionBuilder` instances to build the service definitions. Two type of checks are implemented and can be attached to a service definition by sending `addCheck:` to the builder:
- `ConsulAgentDockerBasedCheck` models a health check using the docker infrastructure and can be used when the services are run in docker containers.
- `ConsulAgentHTTPBasedCheck` models a health check performing an HTTP request and can be combined with the `HealthCheckPlugin` in Stargate.

For more details review the [official Consul documentation on Services](https://www.consul.io/api/agent/service.html) and [Checks](https://www.consul.io/api/agent/check.html).

This plugin does not add any new resources to the `/operations` endpoint available in [Stargate](https://github.com/ba-st/Stargate).
49 changes: 49 additions & 0 deletions source/BaselineOfStargateConsul/BaselineOfStargateConsul.class.st
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
Class {
#name : #BaselineOfStargateConsul,
#superclass : #BaselineOf,
#category : #BaselineOfStargateConsul
}

{ #category : #baselines }
BaselineOfStargateConsul >> baseline: spec [

<baseline>
spec
for: #pharo
do: [ self
setUpDependencies: spec;
setUpPackages: spec.
spec
group: 'CI' with: 'Tests';
group: 'Tools' with: #('Stargate-Tools');
group: 'Development' with: #('Tests' 'Tools')
]
]

{ #category : #accessing }
BaselineOfStargateConsul >> projectClass [

^ MetacelloCypressBaselineProject
]

{ #category : #baselines }
BaselineOfStargateConsul >> setUpDependencies: spec [

spec
baseline: 'Stargate' with: [ spec repository: 'github://ba-st/Stargate:v4/source' ];
project: 'Stargate-Core' copyFrom: 'Stargate' with: [ spec loads: 'Core' ];
project: 'Stargate-SUnit' copyFrom: 'Stargate' with: [ spec loads: 'Dependent-SUnit-Extensions' ];
project: 'Stargate-Tools' copyFrom: 'Stargate' with: [ spec loads: 'Tools' ]
]

{ #category : #baselines }
BaselineOfStargateConsul >> setUpPackages: spec [

spec
package: 'Stargate-Consul' with: [ spec requires: #('Stargate-Core') ];
group: 'Deployment' with: 'Stargate-Consul'.

spec
package: 'Stargate-Consul-Tests' with: [ spec requires: #('Stargate-Consul' 'Stargate-SUnit') ];
group: 'Tests' with: 'Stargate-Consul-Tests'
]
1 change: 1 addition & 0 deletions source/BaselineOfStargateConsul/package.st
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Package { #name : #BaselineOfStargateConsul }
16 changes: 16 additions & 0 deletions source/Stargate-Consul-Tests/ConsulAgentCheckTest.class.st
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"
A ConsulAgentCheckTest is a test class for testing the behavior of ConsulAgentCheck
"
Class {
#name : #ConsulAgentCheckTest,
#superclass : #TestCase,
#category : #'Stargate-Consul-Tests'
}

{ #category : #test }
ConsulAgentCheckTest >> testAsGoTimeFormat [

self
assert: ( ConsulAgentCheck new asGoTimeFormat: 1.5644648441 hours )
equals: '1h33m52s73ms438us760ns'
]
105 changes: 105 additions & 0 deletions source/Stargate-Consul-Tests/ConsulAgentDockerBasedCheckTest.class.st
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
"
A ConsulAgentDockerBasedCheckTest is a test class for testing the behavior of ConsulAgentDockerBasedCheck
"
Class {
#name : #ConsulAgentDockerBasedCheckTest,
#superclass : #TestCase,
#category : #'Stargate-Consul-Tests'
}

{ #category : #tests }
ConsulAgentDockerBasedCheckTest >> testAsJSON [

| check json |

check := ConsulAgentDockerBasedCheck
named: 'Check memory'
executing: '/bin/bash'
withArguments: #('/usr/local/bin/check-memory.sh')
inContainer: 'f972c95ebf0e'
every: 10 seconds.

json := NeoJSONObject fromString: ( NeoJSONWriter toStringPretty: check ).

self
assert: json Name equals: 'Check memory';
assert: json Shell equals: '/bin/bash';
assert: json Args equals: #('/usr/local/bin/check-memory.sh');
assert: json DockerContainerID equals: 'f972c95ebf0e';
assert: json Interval equals: '10s'
]

{ #category : #tests }
ConsulAgentDockerBasedCheckTest >> testCantCreateUnnamed [

self
should: [ ConsulAgentDockerBasedCheck
named: ''
executing: '/bin/bash'
withArguments: #('/usr/local/bin/check-memory.sh')
inContainer: 'f972c95ebf0e'
every: 10 seconds
]
raise: InstanceCreationFailed
withMessageText: 'The check name cannot be empty'
]

{ #category : #tests }
ConsulAgentDockerBasedCheckTest >> testCantCreateWhenShellCommandIsMissing [

self
should: [ ConsulAgentDockerBasedCheck
named: 'xxx'
executing: ''
withArguments: #('/usr/local/bin/check-memory.sh')
inContainer: 'f972c95ebf0e'
every: 10 seconds
]
raise: InstanceCreationFailed
withMessageText: 'The command to execute cannot be empty'
]

{ #category : #tests }
ConsulAgentDockerBasedCheckTest >> testCantCreateWithEmptyContainerId [

self
should: [ ConsulAgentDockerBasedCheck
named: 'xx'
executing: '/bin/bash'
withArguments: #('/usr/local/bin/check-memory.sh')
inContainer: ''
every: 10 seconds
]
raise: InstanceCreationFailed
withMessageText: 'The target container id cannot be empty'
]

{ #category : #tests }
ConsulAgentDockerBasedCheckTest >> testCantCreateWithNegativeDuration [

self
should: [ ConsulAgentDockerBasedCheck
named: 'xx'
executing: '/bin/bash'
withArguments: #('/usr/local/bin/check-memory.sh')
inContainer: 'f972c95ebf0e'
every: -10 seconds
]
raise: InstanceCreationFailed
withMessageText: 'The execution interval must be strictly positive'
]

{ #category : #tests }
ConsulAgentDockerBasedCheckTest >> testCantCreateWithZeroDuration [

self
should: [ ConsulAgentDockerBasedCheck
named: 'xx'
executing: '/bin/bash'
withArguments: #('/usr/local/bin/check-memory.sh')
inContainer: 'f972c95ebf0e'
every: 0 seconds
]
raise: InstanceCreationFailed
withMessageText: 'The execution interval must be strictly positive'
]
136 changes: 136 additions & 0 deletions source/Stargate-Consul-Tests/ConsulAgentHTTPBasedCheckTest.class.st
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
"
A ConsulAgentHTTPBasedCheckTest is a test class for testing the behavior of ConsulAgentHTTPBasedCheck
"
Class {
#name : #ConsulAgentHTTPBasedCheckTest,
#superclass : #TestCase,
#category : #'Stargate-Consul-Tests'
}

{ #category : #tests }
ConsulAgentHTTPBasedCheckTest >> testAsJSON [

| check json |

check := ConsulAgentHTTPBasedCheck
named: 'HTTP check'
executing: #POST
against: 'http://api.example.com' asUrl
withHeaders: #()
every: 10 seconds
timeoutAfter: 1.5 minutes.

json := NeoJSONObject fromString: ( NeoJSONWriter toStringPretty: check ).

self
assert: json Name equals: 'HTTP check';
assert: json Method equals: 'POST';
assert: json Header isEmpty;
assert: json HTTP equals: 'http://api.example.com/';
assert: json Timeout equals: '1m30s';
assert: json Interval equals: '10s'
]

{ #category : #tests }
ConsulAgentHTTPBasedCheckTest >> testAsJSONWhenHeadersArePresent [

| check json |

check := ConsulAgentHTTPBasedCheck
named: 'HTTP check'
executing: #POST
against: 'http://api.example.com' asUrl
withHeaders: { #accept -> ZnMimeType applicationJson }
every: 10 seconds
timeoutAfter: 1.5 minutes.

json := NeoJSONObject fromString: ( NeoJSONWriter toStringPretty: check ).

self
assert: json Name equals: 'HTTP check';
assert: json Method equals: 'POST';
assert: json Header accept equals: 'application/json';
assert: json HTTP equals: 'http://api.example.com/';
assert: json Timeout equals: '1m30s';
assert: json Interval equals: '10s'
]

{ #category : #tests }
ConsulAgentHTTPBasedCheckTest >> testCantCreateUnnamed [

self
should: [ ConsulAgentHTTPBasedCheck
named: ''
executing: #POST
against: 'http://api.example.com' asUrl
withHeaders: #()
every: 10 seconds
timeoutAfter: 1.5 minutes
]
raise: InstanceCreationFailed
withMessageText: 'The check name cannot be empty'
]

{ #category : #tests }
ConsulAgentHTTPBasedCheckTest >> testCantCreateWithNegativeDuration [

self
should: [ ConsulAgentHTTPBasedCheck
named: 'xxx'
executing: #POST
against: 'http://api.example.com' asUrl
withHeaders: #()
every: -10 seconds
timeoutAfter: 1.5 minutes
]
raise: InstanceCreationFailed
withMessageText: 'The execution interval must be strictly positive'
]

{ #category : #tests }
ConsulAgentHTTPBasedCheckTest >> testCantCreateWithNegativeTimeout [

self
should: [ ConsulAgentHTTPBasedCheck
named: 'xxx'
executing: #POST
against: 'http://api.example.com' asUrl
withHeaders: #()
every: 10 seconds
timeoutAfter: -1 minutes
]
raise: InstanceCreationFailed
withMessageText: 'The timeout must be strictly positive'
]

{ #category : #tests }
ConsulAgentHTTPBasedCheckTest >> testCantCreateWithZeroDuration [

self
should: [ ConsulAgentHTTPBasedCheck
named: 'xxx'
executing: #POST
against: 'http://api.example.com' asUrl
withHeaders: #()
every: 0 seconds
timeoutAfter: 1.5 minutes
]
raise: InstanceCreationFailed
withMessageText: 'The execution interval must be strictly positive'
]

{ #category : #tests }
ConsulAgentHTTPBasedCheckTest >> testCantCreateWithZeroTimeout [

self
should: [ ConsulAgentHTTPBasedCheck
named: 'xxx'
executing: #POST
against: 'http://api.example.com' asUrl
withHeaders: #()
every: 10 seconds
timeoutAfter: 0 minutes
]
raise: InstanceCreationFailed
withMessageText: 'The timeout must be strictly positive'
]
Loading

0 comments on commit 151f7ca

Please sign in to comment.