2017-02-01 00:43:57 +00:00
|
|
|
package consul
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
"errors"
|
2017-02-01 00:43:57 +00:00
|
|
|
"fmt"
|
|
|
|
"reflect"
|
2017-08-16 18:27:30 +00:00
|
|
|
"strings"
|
2017-09-14 22:17:21 +00:00
|
|
|
"sync/atomic"
|
2017-02-01 00:43:57 +00:00
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/hashicorp/consul/api"
|
2018-04-17 19:36:50 +00:00
|
|
|
"github.com/hashicorp/nomad/helper/testlog"
|
2018-04-23 23:34:53 +00:00
|
|
|
"github.com/hashicorp/nomad/helper/uuid"
|
2017-02-01 00:43:57 +00:00
|
|
|
"github.com/hashicorp/nomad/nomad/structs"
|
2019-01-04 23:01:35 +00:00
|
|
|
"github.com/hashicorp/nomad/plugins/drivers"
|
2017-08-16 18:27:30 +00:00
|
|
|
"github.com/kr/pretty"
|
2017-12-05 19:39:42 +00:00
|
|
|
"github.com/stretchr/testify/assert"
|
2018-03-15 00:37:54 +00:00
|
|
|
"github.com/stretchr/testify/require"
|
2017-02-01 00:43:57 +00:00
|
|
|
)
|
|
|
|
|
2017-04-18 04:15:13 +00:00
|
|
|
const (
|
2019-11-18 18:04:01 +00:00
|
|
|
// Ports used in testWorkload
|
2017-04-18 04:15:13 +00:00
|
|
|
xPort = 1234
|
|
|
|
yPort = 1235
|
|
|
|
)
|
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
func testWorkload() *WorkloadServices {
|
|
|
|
return &WorkloadServices{
|
2018-04-23 23:34:53 +00:00
|
|
|
AllocID: uuid.Generate(),
|
2019-11-18 18:04:01 +00:00
|
|
|
Task: "taskname",
|
2018-04-23 23:34:53 +00:00
|
|
|
Restarter: &restartRecorder{},
|
2017-02-01 00:43:57 +00:00
|
|
|
Services: []*structs.Service{
|
|
|
|
{
|
|
|
|
Name: "taskname-service",
|
|
|
|
PortLabel: "x",
|
|
|
|
Tags: []string{"tag1", "tag2"},
|
2019-11-13 03:27:54 +00:00
|
|
|
Meta: map[string]string{"meta1": "foo"},
|
2017-02-01 00:43:57 +00:00
|
|
|
},
|
|
|
|
},
|
2018-04-23 23:34:53 +00:00
|
|
|
Networks: []*structs.NetworkResource{
|
|
|
|
{
|
|
|
|
DynamicPorts: []structs.Port{
|
|
|
|
{Label: "x", Value: xPort},
|
|
|
|
{Label: "y", Value: yPort},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2017-02-01 00:43:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
// restartRecorder is a minimal WorkloadRestarter implementation that simply
|
2018-04-23 23:34:53 +00:00
|
|
|
// counts how many restarts were triggered.
|
|
|
|
type restartRecorder struct {
|
|
|
|
restarts int64
|
|
|
|
}
|
|
|
|
|
2018-10-05 02:36:40 +00:00
|
|
|
func (r *restartRecorder) Restart(ctx context.Context, event *structs.TaskEvent, failure bool) error {
|
2018-04-23 23:34:53 +00:00
|
|
|
atomic.AddInt64(&r.restarts, 1)
|
2018-10-05 02:36:40 +00:00
|
|
|
return nil
|
2018-04-23 23:34:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// testFakeCtx contains a fake Consul AgentAPI
|
|
|
|
type testFakeCtx struct {
|
|
|
|
ServiceClient *ServiceClient
|
|
|
|
FakeConsul *MockAgent
|
2019-11-18 18:04:01 +00:00
|
|
|
Workload *WorkloadServices
|
2017-02-01 00:43:57 +00:00
|
|
|
}
|
|
|
|
|
2017-04-08 00:10:26 +00:00
|
|
|
var errNoOps = fmt.Errorf("testing error: no pending operations")
|
|
|
|
|
|
|
|
// syncOps simulates one iteration of the ServiceClient.Run loop and returns
|
|
|
|
// any errors returned by sync() or errNoOps if no pending operations.
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
func (t *testFakeCtx) syncOnce(reason syncReason) error {
|
|
|
|
switch reason {
|
|
|
|
|
|
|
|
case syncPeriodic:
|
|
|
|
err := t.ServiceClient.sync(syncPeriodic)
|
2019-06-14 14:57:46 +00:00
|
|
|
if err == nil {
|
|
|
|
t.ServiceClient.clearExplicitlyDeregistered()
|
|
|
|
}
|
|
|
|
return err
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
|
|
|
|
case syncNewOps:
|
|
|
|
select {
|
|
|
|
case ops := <-t.ServiceClient.opCh:
|
|
|
|
t.ServiceClient.merge(ops)
|
|
|
|
err := t.ServiceClient.sync(syncNewOps)
|
|
|
|
if err == nil {
|
|
|
|
t.ServiceClient.clearExplicitlyDeregistered()
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
default:
|
|
|
|
return errNoOps
|
|
|
|
}
|
|
|
|
|
|
|
|
case syncShutdown:
|
|
|
|
return errors.New("no test for sync due to shutdown")
|
2017-04-08 00:10:26 +00:00
|
|
|
}
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
|
|
|
|
return errors.New("bad sync reason")
|
2017-04-08 00:10:26 +00:00
|
|
|
}
|
|
|
|
|
2017-02-01 00:43:57 +00:00
|
|
|
// setupFake creates a testFakeCtx with a ServiceClient backed by a fakeConsul.
|
2019-11-18 18:04:01 +00:00
|
|
|
// A test Workload is also provided.
|
2018-04-17 19:36:50 +00:00
|
|
|
func setupFake(t *testing.T) *testFakeCtx {
|
2017-09-13 06:15:46 +00:00
|
|
|
fc := NewMockAgent()
|
2019-11-18 18:04:01 +00:00
|
|
|
tw := testWorkload()
|
2019-06-14 14:57:46 +00:00
|
|
|
|
|
|
|
// by default start fake client being out of probation
|
|
|
|
sc := NewServiceClient(fc, testlog.HCLogger(t), true)
|
|
|
|
sc.deregisterProbationExpiry = time.Now().Add(-1 * time.Minute)
|
|
|
|
|
2017-02-01 00:43:57 +00:00
|
|
|
return &testFakeCtx{
|
2019-06-14 14:57:46 +00:00
|
|
|
ServiceClient: sc,
|
2017-02-01 00:43:57 +00:00
|
|
|
FakeConsul: fc,
|
2019-11-18 18:04:01 +00:00
|
|
|
Workload: tw,
|
2017-02-01 00:43:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestConsul_ChangeTags(t *testing.T) {
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
t.Parallel()
|
2018-04-17 19:36:50 +00:00
|
|
|
ctx := setupFake(t)
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
r := require.New(t)
|
2017-02-01 00:43:57 +00:00
|
|
|
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
r.NoError(ctx.ServiceClient.RegisterWorkload(ctx.Workload))
|
|
|
|
r.NoError(ctx.syncOnce(syncNewOps))
|
|
|
|
r.Equal(1, len(ctx.FakeConsul.services), "Expected 1 service to be registered with Consul")
|
2017-02-01 00:43:57 +00:00
|
|
|
|
consul: Use a stable identifier for services
The current implementation of Service Registration uses a hash of the
nomad-internal state of a service to register it with Consul, this means that
any update to the service invalidates this name and we then deregister, and
recreate the service in Consul.
While this behaviour slightly simplifies reasoning about service registration,
this becomes problematic when we add consul health checks to a service. When
the service is re-registered, so are the checks, which default to failing for
at least one check period.
This commit migrates us to using a stable identifier based on the
allocation, task, and service identifiers, and uses the difference
between the remote and local state to decide when to push updates.
It uses the existing hashing mechanic to decide when UpdateTask should
regenerate service registrations for providing to Sync, but this should
be removable as part of a future refactor.
It additionally introduces the _nomad-check- prefix for check
definitions, to allow for future allowing of consul features like
maintenance mode.
2019-04-10 08:39:24 +00:00
|
|
|
// Validate the alloc registration
|
2019-11-18 18:04:01 +00:00
|
|
|
reg1, err := ctx.ServiceClient.AllocRegistrations(ctx.Workload.AllocID)
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
r.NoError(err)
|
|
|
|
r.NotNil(reg1, "Unexpected nil alloc registration")
|
|
|
|
r.Equal(1, reg1.NumServices())
|
|
|
|
r.Equal(0, reg1.NumChecks())
|
2017-08-07 22:54:05 +00:00
|
|
|
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
serviceBefore := ctx.FakeConsul.lookupService("taskname-service")[0]
|
|
|
|
r.Equal(serviceBefore.Name, ctx.Workload.Services[0].Name)
|
|
|
|
r.Equal(serviceBefore.Tags, ctx.Workload.Services[0].Tags)
|
2017-02-01 00:43:57 +00:00
|
|
|
|
consul: Use a stable identifier for services
The current implementation of Service Registration uses a hash of the
nomad-internal state of a service to register it with Consul, this means that
any update to the service invalidates this name and we then deregister, and
recreate the service in Consul.
While this behaviour slightly simplifies reasoning about service registration,
this becomes problematic when we add consul health checks to a service. When
the service is re-registered, so are the checks, which default to failing for
at least one check period.
This commit migrates us to using a stable identifier based on the
allocation, task, and service identifiers, and uses the difference
between the remote and local state to decide when to push updates.
It uses the existing hashing mechanic to decide when UpdateTask should
regenerate service registrations for providing to Sync, but this should
be removable as part of a future refactor.
It additionally introduces the _nomad-check- prefix for check
definitions, to allow for future allowing of consul features like
maintenance mode.
2019-04-10 08:39:24 +00:00
|
|
|
// Update the task definition
|
2019-11-18 18:04:01 +00:00
|
|
|
origWorkload := ctx.Workload.Copy()
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
ctx.Workload.Services[0].Tags[0] = "new-tag"
|
2017-02-01 00:43:57 +00:00
|
|
|
|
consul: Use a stable identifier for services
The current implementation of Service Registration uses a hash of the
nomad-internal state of a service to register it with Consul, this means that
any update to the service invalidates this name and we then deregister, and
recreate the service in Consul.
While this behaviour slightly simplifies reasoning about service registration,
this becomes problematic when we add consul health checks to a service. When
the service is re-registered, so are the checks, which default to failing for
at least one check period.
This commit migrates us to using a stable identifier based on the
allocation, task, and service identifiers, and uses the difference
between the remote and local state to decide when to push updates.
It uses the existing hashing mechanic to decide when UpdateTask should
regenerate service registrations for providing to Sync, but this should
be removable as part of a future refactor.
It additionally introduces the _nomad-check- prefix for check
definitions, to allow for future allowing of consul features like
maintenance mode.
2019-04-10 08:39:24 +00:00
|
|
|
// Register and sync the update
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
r.NoError(ctx.ServiceClient.UpdateWorkload(origWorkload, ctx.Workload))
|
|
|
|
r.NoError(ctx.syncOnce(syncNewOps))
|
|
|
|
r.Equal(1, len(ctx.FakeConsul.services), "Expected 1 service to be registered with Consul")
|
|
|
|
|
|
|
|
// Validate the consul service definition changed
|
|
|
|
serviceAfter := ctx.FakeConsul.lookupService("taskname-service")[0]
|
|
|
|
r.Equal(serviceAfter.Name, ctx.Workload.Services[0].Name)
|
|
|
|
r.Equal(serviceAfter.Tags, ctx.Workload.Services[0].Tags)
|
|
|
|
r.Equal("new-tag", serviceAfter.Tags[0])
|
|
|
|
}
|
2017-08-07 22:54:05 +00:00
|
|
|
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
func TestConsul_EnableTagOverride_Syncs(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
ctx := setupFake(t)
|
|
|
|
r := require.New(t)
|
|
|
|
|
|
|
|
// Configure our test service to set EnableTagOverride = true
|
|
|
|
ctx.Workload.Services[0].EnableTagOverride = true
|
|
|
|
|
|
|
|
r.NoError(ctx.ServiceClient.RegisterWorkload(ctx.Workload))
|
|
|
|
r.NoError(ctx.syncOnce(syncNewOps))
|
|
|
|
r.Equal(1, len(ctx.FakeConsul.services))
|
|
|
|
|
|
|
|
// Validate the alloc registration
|
|
|
|
reg1, err := ctx.ServiceClient.AllocRegistrations(ctx.Workload.AllocID)
|
|
|
|
r.NoError(err)
|
|
|
|
r.NotNil(reg1)
|
|
|
|
r.Equal(1, reg1.NumServices())
|
|
|
|
r.Equal(0, reg1.NumChecks())
|
|
|
|
|
|
|
|
const service = "taskname-service"
|
|
|
|
|
|
|
|
// sanity check things are what we expect
|
|
|
|
consulServiceDefBefore := ctx.FakeConsul.lookupService(service)[0]
|
|
|
|
r.Equal(ctx.Workload.Services[0].Name, consulServiceDefBefore.Name)
|
|
|
|
r.Equal([]string{"tag1", "tag2"}, consulServiceDefBefore.Tags)
|
|
|
|
r.True(consulServiceDefBefore.EnableTagOverride)
|
|
|
|
|
|
|
|
// manually set the tags in consul
|
|
|
|
ctx.FakeConsul.lookupService(service)[0].Tags = []string{"new", "tags"}
|
|
|
|
|
|
|
|
// do a periodic sync (which will respect EnableTagOverride)
|
|
|
|
r.NoError(ctx.syncOnce(syncPeriodic))
|
|
|
|
r.Equal(1, len(ctx.FakeConsul.services))
|
|
|
|
consulServiceDefAfter := ctx.FakeConsul.lookupService(service)[0]
|
|
|
|
r.Equal([]string{"new", "tags"}, consulServiceDefAfter.Tags) // manually set tags should still be there
|
|
|
|
|
|
|
|
// now do a new-ops sync (which will override EnableTagOverride)
|
|
|
|
r.NoError(ctx.ServiceClient.RegisterWorkload(ctx.Workload))
|
|
|
|
r.NoError(ctx.syncOnce(syncNewOps))
|
|
|
|
r.Equal(1, len(ctx.FakeConsul.services))
|
|
|
|
consulServiceDefUpdated := ctx.FakeConsul.lookupService(service)[0]
|
|
|
|
r.Equal([]string{"tag1", "tag2"}, consulServiceDefUpdated.Tags) // jobspec tags should be set now
|
2017-02-01 00:43:57 +00:00
|
|
|
}
|
|
|
|
|
2017-04-18 04:15:13 +00:00
|
|
|
// TestConsul_ChangePorts asserts that changing the ports on a service updates
|
2017-12-08 01:08:25 +00:00
|
|
|
// it in Consul. Pre-0.7.1 ports were not part of the service ID and this was a
|
|
|
|
// slightly different code path than changing tags.
|
2017-04-18 04:15:13 +00:00
|
|
|
func TestConsul_ChangePorts(t *testing.T) {
|
2018-04-17 19:36:50 +00:00
|
|
|
ctx := setupFake(t)
|
consul: Use a stable identifier for services
The current implementation of Service Registration uses a hash of the
nomad-internal state of a service to register it with Consul, this means that
any update to the service invalidates this name and we then deregister, and
recreate the service in Consul.
While this behaviour slightly simplifies reasoning about service registration,
this becomes problematic when we add consul health checks to a service. When
the service is re-registered, so are the checks, which default to failing for
at least one check period.
This commit migrates us to using a stable identifier based on the
allocation, task, and service identifiers, and uses the difference
between the remote and local state to decide when to push updates.
It uses the existing hashing mechanic to decide when UpdateTask should
regenerate service registrations for providing to Sync, but this should
be removable as part of a future refactor.
It additionally introduces the _nomad-check- prefix for check
definitions, to allow for future allowing of consul features like
maintenance mode.
2019-04-10 08:39:24 +00:00
|
|
|
require := require.New(t)
|
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
ctx.Workload.Services[0].Checks = []*structs.ServiceCheck{
|
2017-04-18 04:15:13 +00:00
|
|
|
{
|
|
|
|
Name: "c1",
|
|
|
|
Type: "tcp",
|
|
|
|
Interval: time.Second,
|
|
|
|
Timeout: time.Second,
|
|
|
|
PortLabel: "x",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "c2",
|
|
|
|
Type: "script",
|
|
|
|
Interval: 9000 * time.Hour,
|
|
|
|
Timeout: time.Second,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "c3",
|
|
|
|
Type: "http",
|
|
|
|
Protocol: "http",
|
|
|
|
Path: "/",
|
|
|
|
Interval: time.Second,
|
|
|
|
Timeout: time.Second,
|
|
|
|
PortLabel: "y",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
require.NoError(ctx.ServiceClient.RegisterWorkload(ctx.Workload))
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
require.NoError(ctx.syncOnce(syncNewOps))
|
consul: Use a stable identifier for services
The current implementation of Service Registration uses a hash of the
nomad-internal state of a service to register it with Consul, this means that
any update to the service invalidates this name and we then deregister, and
recreate the service in Consul.
While this behaviour slightly simplifies reasoning about service registration,
this becomes problematic when we add consul health checks to a service. When
the service is re-registered, so are the checks, which default to failing for
at least one check period.
This commit migrates us to using a stable identifier based on the
allocation, task, and service identifiers, and uses the difference
between the remote and local state to decide when to push updates.
It uses the existing hashing mechanic to decide when UpdateTask should
regenerate service registrations for providing to Sync, but this should
be removable as part of a future refactor.
It additionally introduces the _nomad-check- prefix for check
definitions, to allow for future allowing of consul features like
maintenance mode.
2019-04-10 08:39:24 +00:00
|
|
|
require.Equal(1, len(ctx.FakeConsul.services), "Expected 1 service to be registered with Consul")
|
2017-04-18 04:15:13 +00:00
|
|
|
|
consul: Use a stable identifier for services
The current implementation of Service Registration uses a hash of the
nomad-internal state of a service to register it with Consul, this means that
any update to the service invalidates this name and we then deregister, and
recreate the service in Consul.
While this behaviour slightly simplifies reasoning about service registration,
this becomes problematic when we add consul health checks to a service. When
the service is re-registered, so are the checks, which default to failing for
at least one check period.
This commit migrates us to using a stable identifier based on the
allocation, task, and service identifiers, and uses the difference
between the remote and local state to decide when to push updates.
It uses the existing hashing mechanic to decide when UpdateTask should
regenerate service registrations for providing to Sync, but this should
be removable as part of a future refactor.
It additionally introduces the _nomad-check- prefix for check
definitions, to allow for future allowing of consul features like
maintenance mode.
2019-04-10 08:39:24 +00:00
|
|
|
for _, v := range ctx.FakeConsul.services {
|
2019-11-18 18:04:01 +00:00
|
|
|
require.Equal(ctx.Workload.Services[0].Name, v.Name)
|
|
|
|
require.Equal(ctx.Workload.Services[0].Tags, v.Tags)
|
consul: Use a stable identifier for services
The current implementation of Service Registration uses a hash of the
nomad-internal state of a service to register it with Consul, this means that
any update to the service invalidates this name and we then deregister, and
recreate the service in Consul.
While this behaviour slightly simplifies reasoning about service registration,
this becomes problematic when we add consul health checks to a service. When
the service is re-registered, so are the checks, which default to failing for
at least one check period.
This commit migrates us to using a stable identifier based on the
allocation, task, and service identifiers, and uses the difference
between the remote and local state to decide when to push updates.
It uses the existing hashing mechanic to decide when UpdateTask should
regenerate service registrations for providing to Sync, but this should
be removable as part of a future refactor.
It additionally introduces the _nomad-check- prefix for check
definitions, to allow for future allowing of consul features like
maintenance mode.
2019-04-10 08:39:24 +00:00
|
|
|
require.Equal(xPort, v.Port)
|
2017-04-18 04:15:13 +00:00
|
|
|
}
|
|
|
|
|
2019-06-13 12:57:27 +00:00
|
|
|
require.Len(ctx.FakeConsul.checks, 3)
|
2017-04-18 04:15:13 +00:00
|
|
|
|
|
|
|
origTCPKey := ""
|
|
|
|
origScriptKey := ""
|
|
|
|
origHTTPKey := ""
|
|
|
|
for k, v := range ctx.FakeConsul.checks {
|
|
|
|
switch v.Name {
|
|
|
|
case "c1":
|
|
|
|
origTCPKey = k
|
consul: Use a stable identifier for services
The current implementation of Service Registration uses a hash of the
nomad-internal state of a service to register it with Consul, this means that
any update to the service invalidates this name and we then deregister, and
recreate the service in Consul.
While this behaviour slightly simplifies reasoning about service registration,
this becomes problematic when we add consul health checks to a service. When
the service is re-registered, so are the checks, which default to failing for
at least one check period.
This commit migrates us to using a stable identifier based on the
allocation, task, and service identifiers, and uses the difference
between the remote and local state to decide when to push updates.
It uses the existing hashing mechanic to decide when UpdateTask should
regenerate service registrations for providing to Sync, but this should
be removable as part of a future refactor.
It additionally introduces the _nomad-check- prefix for check
definitions, to allow for future allowing of consul features like
maintenance mode.
2019-04-10 08:39:24 +00:00
|
|
|
require.Equal(fmt.Sprintf(":%d", xPort), v.TCP)
|
2017-04-18 04:15:13 +00:00
|
|
|
case "c2":
|
|
|
|
origScriptKey = k
|
|
|
|
case "c3":
|
|
|
|
origHTTPKey = k
|
consul: Use a stable identifier for services
The current implementation of Service Registration uses a hash of the
nomad-internal state of a service to register it with Consul, this means that
any update to the service invalidates this name and we then deregister, and
recreate the service in Consul.
While this behaviour slightly simplifies reasoning about service registration,
this becomes problematic when we add consul health checks to a service. When
the service is re-registered, so are the checks, which default to failing for
at least one check period.
This commit migrates us to using a stable identifier based on the
allocation, task, and service identifiers, and uses the difference
between the remote and local state to decide when to push updates.
It uses the existing hashing mechanic to decide when UpdateTask should
regenerate service registrations for providing to Sync, but this should
be removable as part of a future refactor.
It additionally introduces the _nomad-check- prefix for check
definitions, to allow for future allowing of consul features like
maintenance mode.
2019-04-10 08:39:24 +00:00
|
|
|
require.Equal(fmt.Sprintf("http://:%d/", yPort), v.HTTP)
|
2017-04-18 04:15:13 +00:00
|
|
|
default:
|
|
|
|
t.Fatalf("unexpected check: %q", v.Name)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
consul: Use a stable identifier for services
The current implementation of Service Registration uses a hash of the
nomad-internal state of a service to register it with Consul, this means that
any update to the service invalidates this name and we then deregister, and
recreate the service in Consul.
While this behaviour slightly simplifies reasoning about service registration,
this becomes problematic when we add consul health checks to a service. When
the service is re-registered, so are the checks, which default to failing for
at least one check period.
This commit migrates us to using a stable identifier based on the
allocation, task, and service identifiers, and uses the difference
between the remote and local state to decide when to push updates.
It uses the existing hashing mechanic to decide when UpdateTask should
regenerate service registrations for providing to Sync, but this should
be removable as part of a future refactor.
It additionally introduces the _nomad-check- prefix for check
definitions, to allow for future allowing of consul features like
maintenance mode.
2019-04-10 08:39:24 +00:00
|
|
|
require.NotEmpty(origTCPKey)
|
|
|
|
require.NotEmpty(origScriptKey)
|
|
|
|
require.NotEmpty(origHTTPKey)
|
|
|
|
|
2017-04-18 04:15:13 +00:00
|
|
|
// Now update the PortLabel on the Service and Check c3
|
2019-11-18 18:04:01 +00:00
|
|
|
origWorkload := ctx.Workload.Copy()
|
|
|
|
ctx.Workload.Services[0].PortLabel = "y"
|
|
|
|
ctx.Workload.Services[0].Checks = []*structs.ServiceCheck{
|
2017-04-18 04:15:13 +00:00
|
|
|
{
|
|
|
|
Name: "c1",
|
|
|
|
Type: "tcp",
|
|
|
|
Interval: time.Second,
|
|
|
|
Timeout: time.Second,
|
|
|
|
PortLabel: "x",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "c2",
|
|
|
|
Type: "script",
|
|
|
|
Interval: 9000 * time.Hour,
|
|
|
|
Timeout: time.Second,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "c3",
|
|
|
|
Type: "http",
|
|
|
|
Protocol: "http",
|
|
|
|
Path: "/",
|
|
|
|
Interval: time.Second,
|
|
|
|
Timeout: time.Second,
|
2017-06-13 21:02:11 +00:00
|
|
|
// Removed PortLabel; should default to service's (y)
|
2017-04-18 04:15:13 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
require.NoError(ctx.ServiceClient.UpdateWorkload(origWorkload, ctx.Workload))
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
require.NoError(ctx.syncOnce(syncNewOps))
|
consul: Use a stable identifier for services
The current implementation of Service Registration uses a hash of the
nomad-internal state of a service to register it with Consul, this means that
any update to the service invalidates this name and we then deregister, and
recreate the service in Consul.
While this behaviour slightly simplifies reasoning about service registration,
this becomes problematic when we add consul health checks to a service. When
the service is re-registered, so are the checks, which default to failing for
at least one check period.
This commit migrates us to using a stable identifier based on the
allocation, task, and service identifiers, and uses the difference
between the remote and local state to decide when to push updates.
It uses the existing hashing mechanic to decide when UpdateTask should
regenerate service registrations for providing to Sync, but this should
be removable as part of a future refactor.
It additionally introduces the _nomad-check- prefix for check
definitions, to allow for future allowing of consul features like
maintenance mode.
2019-04-10 08:39:24 +00:00
|
|
|
require.Equal(1, len(ctx.FakeConsul.services), "Expected 1 service to be registered with Consul")
|
2017-04-18 04:15:13 +00:00
|
|
|
|
consul: Use a stable identifier for services
The current implementation of Service Registration uses a hash of the
nomad-internal state of a service to register it with Consul, this means that
any update to the service invalidates this name and we then deregister, and
recreate the service in Consul.
While this behaviour slightly simplifies reasoning about service registration,
this becomes problematic when we add consul health checks to a service. When
the service is re-registered, so are the checks, which default to failing for
at least one check period.
This commit migrates us to using a stable identifier based on the
allocation, task, and service identifiers, and uses the difference
between the remote and local state to decide when to push updates.
It uses the existing hashing mechanic to decide when UpdateTask should
regenerate service registrations for providing to Sync, but this should
be removable as part of a future refactor.
It additionally introduces the _nomad-check- prefix for check
definitions, to allow for future allowing of consul features like
maintenance mode.
2019-04-10 08:39:24 +00:00
|
|
|
for _, v := range ctx.FakeConsul.services {
|
2019-11-18 18:04:01 +00:00
|
|
|
require.Equal(ctx.Workload.Services[0].Name, v.Name)
|
|
|
|
require.Equal(ctx.Workload.Services[0].Tags, v.Tags)
|
consul: Use a stable identifier for services
The current implementation of Service Registration uses a hash of the
nomad-internal state of a service to register it with Consul, this means that
any update to the service invalidates this name and we then deregister, and
recreate the service in Consul.
While this behaviour slightly simplifies reasoning about service registration,
this becomes problematic when we add consul health checks to a service. When
the service is re-registered, so are the checks, which default to failing for
at least one check period.
This commit migrates us to using a stable identifier based on the
allocation, task, and service identifiers, and uses the difference
between the remote and local state to decide when to push updates.
It uses the existing hashing mechanic to decide when UpdateTask should
regenerate service registrations for providing to Sync, but this should
be removable as part of a future refactor.
It additionally introduces the _nomad-check- prefix for check
definitions, to allow for future allowing of consul features like
maintenance mode.
2019-04-10 08:39:24 +00:00
|
|
|
require.Equal(yPort, v.Port)
|
2017-04-18 04:15:13 +00:00
|
|
|
}
|
|
|
|
|
consul: Use a stable identifier for services
The current implementation of Service Registration uses a hash of the
nomad-internal state of a service to register it with Consul, this means that
any update to the service invalidates this name and we then deregister, and
recreate the service in Consul.
While this behaviour slightly simplifies reasoning about service registration,
this becomes problematic when we add consul health checks to a service. When
the service is re-registered, so are the checks, which default to failing for
at least one check period.
This commit migrates us to using a stable identifier based on the
allocation, task, and service identifiers, and uses the difference
between the remote and local state to decide when to push updates.
It uses the existing hashing mechanic to decide when UpdateTask should
regenerate service registrations for providing to Sync, but this should
be removable as part of a future refactor.
It additionally introduces the _nomad-check- prefix for check
definitions, to allow for future allowing of consul features like
maintenance mode.
2019-04-10 08:39:24 +00:00
|
|
|
require.Equal(3, len(ctx.FakeConsul.checks))
|
2017-04-18 04:15:13 +00:00
|
|
|
|
|
|
|
for k, v := range ctx.FakeConsul.checks {
|
|
|
|
switch v.Name {
|
|
|
|
case "c1":
|
2019-06-13 12:57:27 +00:00
|
|
|
// C1 is changed because the service was re-registered
|
|
|
|
require.NotEqual(origTCPKey, k)
|
consul: Use a stable identifier for services
The current implementation of Service Registration uses a hash of the
nomad-internal state of a service to register it with Consul, this means that
any update to the service invalidates this name and we then deregister, and
recreate the service in Consul.
While this behaviour slightly simplifies reasoning about service registration,
this becomes problematic when we add consul health checks to a service. When
the service is re-registered, so are the checks, which default to failing for
at least one check period.
This commit migrates us to using a stable identifier based on the
allocation, task, and service identifiers, and uses the difference
between the remote and local state to decide when to push updates.
It uses the existing hashing mechanic to decide when UpdateTask should
regenerate service registrations for providing to Sync, but this should
be removable as part of a future refactor.
It additionally introduces the _nomad-check- prefix for check
definitions, to allow for future allowing of consul features like
maintenance mode.
2019-04-10 08:39:24 +00:00
|
|
|
require.Equal(fmt.Sprintf(":%d", xPort), v.TCP)
|
2017-04-18 04:15:13 +00:00
|
|
|
case "c2":
|
2019-06-13 12:57:27 +00:00
|
|
|
// C2 is changed because the service was re-registered
|
|
|
|
require.NotEqual(origScriptKey, k)
|
2017-04-18 04:15:13 +00:00
|
|
|
case "c3":
|
consul: Use a stable identifier for services
The current implementation of Service Registration uses a hash of the
nomad-internal state of a service to register it with Consul, this means that
any update to the service invalidates this name and we then deregister, and
recreate the service in Consul.
While this behaviour slightly simplifies reasoning about service registration,
this becomes problematic when we add consul health checks to a service. When
the service is re-registered, so are the checks, which default to failing for
at least one check period.
This commit migrates us to using a stable identifier based on the
allocation, task, and service identifiers, and uses the difference
between the remote and local state to decide when to push updates.
It uses the existing hashing mechanic to decide when UpdateTask should
regenerate service registrations for providing to Sync, but this should
be removable as part of a future refactor.
It additionally introduces the _nomad-check- prefix for check
definitions, to allow for future allowing of consul features like
maintenance mode.
2019-04-10 08:39:24 +00:00
|
|
|
require.NotEqual(origHTTPKey, k)
|
|
|
|
require.Equal(fmt.Sprintf("http://:%d/", yPort), v.HTTP)
|
2017-04-18 04:15:13 +00:00
|
|
|
default:
|
2017-08-07 21:13:05 +00:00
|
|
|
t.Errorf("Unknown check: %q", k)
|
2017-04-18 04:15:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-16 23:35:16 +00:00
|
|
|
// TestConsul_ChangeChecks asserts that updating only the checks on a service
|
|
|
|
// properly syncs with Consul.
|
|
|
|
func TestConsul_ChangeChecks(t *testing.T) {
|
2018-04-17 19:36:50 +00:00
|
|
|
ctx := setupFake(t)
|
2019-11-18 18:04:01 +00:00
|
|
|
ctx.Workload.Services[0].Checks = []*structs.ServiceCheck{
|
2017-06-16 23:35:16 +00:00
|
|
|
{
|
|
|
|
Name: "c1",
|
|
|
|
Type: "tcp",
|
|
|
|
Interval: time.Second,
|
|
|
|
Timeout: time.Second,
|
|
|
|
PortLabel: "x",
|
2017-09-14 22:17:21 +00:00
|
|
|
CheckRestart: &structs.CheckRestart{
|
|
|
|
Limit: 3,
|
|
|
|
},
|
2017-06-16 23:35:16 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
if err := ctx.ServiceClient.RegisterWorkload(ctx.Workload); err != nil {
|
2017-06-16 23:35:16 +00:00
|
|
|
t.Fatalf("unexpected error registering task: %v", err)
|
|
|
|
}
|
|
|
|
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
if err := ctx.syncOnce(syncNewOps); err != nil {
|
2017-06-16 23:35:16 +00:00
|
|
|
t.Fatalf("unexpected error syncing task: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if n := len(ctx.FakeConsul.services); n != 1 {
|
|
|
|
t.Fatalf("expected 1 service but found %d:\n%#v", n, ctx.FakeConsul.services)
|
|
|
|
}
|
|
|
|
|
2017-09-14 22:17:21 +00:00
|
|
|
// Assert a check restart watch update was enqueued and clear it
|
|
|
|
if n := len(ctx.ServiceClient.checkWatcher.checkUpdateCh); n != 1 {
|
|
|
|
t.Fatalf("expected 1 check restart update but found %d", n)
|
|
|
|
}
|
|
|
|
upd := <-ctx.ServiceClient.checkWatcher.checkUpdateCh
|
|
|
|
c1ID := upd.checkID
|
|
|
|
|
2017-08-07 22:54:05 +00:00
|
|
|
// Query the allocs registrations and then again when we update. The IDs
|
|
|
|
// should change
|
2019-11-18 18:04:01 +00:00
|
|
|
reg1, err := ctx.ServiceClient.AllocRegistrations(ctx.Workload.AllocID)
|
2017-08-07 22:54:05 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Looking up alloc registration failed: %v", err)
|
|
|
|
}
|
|
|
|
if reg1 == nil {
|
|
|
|
t.Fatalf("Nil alloc registrations: %v", err)
|
|
|
|
}
|
|
|
|
if num := reg1.NumServices(); num != 1 {
|
2018-03-11 18:53:58 +00:00
|
|
|
t.Fatalf("Wrong number of services: got %d; want 1", num)
|
2017-08-07 22:54:05 +00:00
|
|
|
}
|
|
|
|
if num := reg1.NumChecks(); num != 1 {
|
|
|
|
t.Fatalf("Wrong number of checks: got %d; want 1", num)
|
|
|
|
}
|
|
|
|
|
2017-06-16 23:35:16 +00:00
|
|
|
origServiceKey := ""
|
|
|
|
for k, v := range ctx.FakeConsul.services {
|
|
|
|
origServiceKey = k
|
2019-11-18 18:04:01 +00:00
|
|
|
if v.Name != ctx.Workload.Services[0].Name {
|
|
|
|
t.Errorf("expected Name=%q != %q", ctx.Workload.Services[0].Name, v.Name)
|
2017-06-16 23:35:16 +00:00
|
|
|
}
|
|
|
|
if v.Port != xPort {
|
|
|
|
t.Errorf("expected Port x=%v but found: %v", xPort, v.Port)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if n := len(ctx.FakeConsul.checks); n != 1 {
|
|
|
|
t.Fatalf("expected 1 check but found %d:\n%#v", n, ctx.FakeConsul.checks)
|
|
|
|
}
|
|
|
|
for _, v := range ctx.FakeConsul.checks {
|
|
|
|
if v.Name != "c1" {
|
|
|
|
t.Fatalf("expected check c1 but found %q", v.Name)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-07 22:54:05 +00:00
|
|
|
// Now add a check and modify the original
|
2019-11-18 18:04:01 +00:00
|
|
|
origWorkload := ctx.Workload.Copy()
|
|
|
|
ctx.Workload.Services[0].Checks = []*structs.ServiceCheck{
|
2017-06-16 23:35:16 +00:00
|
|
|
{
|
|
|
|
Name: "c1",
|
|
|
|
Type: "tcp",
|
2017-08-07 22:54:05 +00:00
|
|
|
Interval: 2 * time.Second,
|
2017-06-16 23:35:16 +00:00
|
|
|
Timeout: time.Second,
|
|
|
|
PortLabel: "x",
|
2017-09-14 22:17:21 +00:00
|
|
|
CheckRestart: &structs.CheckRestart{
|
|
|
|
Limit: 3,
|
|
|
|
},
|
2017-06-16 23:35:16 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "c2",
|
|
|
|
Type: "http",
|
|
|
|
Path: "/",
|
|
|
|
Interval: time.Second,
|
|
|
|
Timeout: time.Second,
|
|
|
|
PortLabel: "x",
|
|
|
|
},
|
|
|
|
}
|
2019-11-18 18:04:01 +00:00
|
|
|
if err := ctx.ServiceClient.UpdateWorkload(origWorkload, ctx.Workload); err != nil {
|
2017-06-16 23:35:16 +00:00
|
|
|
t.Fatalf("unexpected error registering task: %v", err)
|
|
|
|
}
|
2017-09-14 22:17:21 +00:00
|
|
|
|
|
|
|
// Assert 2 check restart watch updates was enqueued
|
|
|
|
if n := len(ctx.ServiceClient.checkWatcher.checkUpdateCh); n != 2 {
|
|
|
|
t.Fatalf("expected 2 check restart updates but found %d", n)
|
|
|
|
}
|
|
|
|
|
|
|
|
// First the new watch
|
|
|
|
upd = <-ctx.ServiceClient.checkWatcher.checkUpdateCh
|
|
|
|
if upd.checkID == c1ID || upd.remove {
|
|
|
|
t.Fatalf("expected check watch update to be an add of checkID=%q but found remove=%t checkID=%q",
|
|
|
|
c1ID, upd.remove, upd.checkID)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Then remove the old watch
|
|
|
|
upd = <-ctx.ServiceClient.checkWatcher.checkUpdateCh
|
|
|
|
if upd.checkID != c1ID || !upd.remove {
|
|
|
|
t.Fatalf("expected check watch update to be a removal of checkID=%q but found remove=%t checkID=%q",
|
|
|
|
c1ID, upd.remove, upd.checkID)
|
|
|
|
}
|
|
|
|
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
if err := ctx.syncOnce(syncNewOps); err != nil {
|
2017-06-16 23:35:16 +00:00
|
|
|
t.Fatalf("unexpected error syncing task: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if n := len(ctx.FakeConsul.services); n != 1 {
|
|
|
|
t.Fatalf("expected 1 service but found %d:\n%#v", n, ctx.FakeConsul.services)
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, ok := ctx.FakeConsul.services[origServiceKey]; !ok {
|
|
|
|
t.Errorf("unexpected key change; was: %q -- but found %#v", origServiceKey, ctx.FakeConsul.services)
|
|
|
|
}
|
|
|
|
|
|
|
|
if n := len(ctx.FakeConsul.checks); n != 2 {
|
|
|
|
t.Fatalf("expected 2 check but found %d:\n%#v", n, ctx.FakeConsul.checks)
|
|
|
|
}
|
|
|
|
|
|
|
|
for k, v := range ctx.FakeConsul.checks {
|
|
|
|
switch v.Name {
|
|
|
|
case "c1":
|
|
|
|
if expected := fmt.Sprintf(":%d", xPort); v.TCP != expected {
|
|
|
|
t.Errorf("expected Port x=%v but found: %v", expected, v.TCP)
|
|
|
|
}
|
2017-09-14 22:17:21 +00:00
|
|
|
|
|
|
|
// update id
|
|
|
|
c1ID = k
|
2017-06-16 23:35:16 +00:00
|
|
|
case "c2":
|
|
|
|
if expected := fmt.Sprintf("http://:%d/", xPort); v.HTTP != expected {
|
|
|
|
t.Errorf("expected Port x=%v but found: %v", expected, v.HTTP)
|
|
|
|
}
|
|
|
|
default:
|
2017-08-07 21:13:05 +00:00
|
|
|
t.Errorf("Unknown check: %q", k)
|
2017-06-16 23:35:16 +00:00
|
|
|
}
|
|
|
|
}
|
2017-08-07 22:54:05 +00:00
|
|
|
|
|
|
|
// Check again and ensure the IDs changed
|
2019-11-18 18:04:01 +00:00
|
|
|
reg2, err := ctx.ServiceClient.AllocRegistrations(ctx.Workload.AllocID)
|
2017-08-07 22:54:05 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Looking up alloc registration failed: %v", err)
|
|
|
|
}
|
|
|
|
if reg2 == nil {
|
|
|
|
t.Fatalf("Nil alloc registrations: %v", err)
|
|
|
|
}
|
|
|
|
if num := reg2.NumServices(); num != 1 {
|
2018-03-11 18:53:58 +00:00
|
|
|
t.Fatalf("Wrong number of services: got %d; want 1", num)
|
2017-08-07 22:54:05 +00:00
|
|
|
}
|
|
|
|
if num := reg2.NumChecks(); num != 2 {
|
|
|
|
t.Fatalf("Wrong number of checks: got %d; want 2", num)
|
|
|
|
}
|
|
|
|
|
|
|
|
for task, treg := range reg1.Tasks {
|
|
|
|
otherTaskReg, ok := reg2.Tasks[task]
|
|
|
|
if !ok {
|
|
|
|
t.Fatalf("Task %q not in second reg", task)
|
|
|
|
}
|
|
|
|
|
|
|
|
for sID, sreg := range treg.Services {
|
|
|
|
otherServiceReg, ok := otherTaskReg.Services[sID]
|
|
|
|
if !ok {
|
|
|
|
t.Fatalf("service ID changed")
|
|
|
|
}
|
|
|
|
|
|
|
|
for newID := range sreg.checkIDs {
|
|
|
|
if _, ok := otherServiceReg.checkIDs[newID]; ok {
|
|
|
|
t.Fatalf("check IDs should change")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-09-14 22:17:21 +00:00
|
|
|
|
|
|
|
// Alter a CheckRestart and make sure the watcher is updated but nothing else
|
2019-11-18 18:04:01 +00:00
|
|
|
origWorkload = ctx.Workload.Copy()
|
|
|
|
ctx.Workload.Services[0].Checks = []*structs.ServiceCheck{
|
2017-09-14 22:17:21 +00:00
|
|
|
{
|
|
|
|
Name: "c1",
|
|
|
|
Type: "tcp",
|
|
|
|
Interval: 2 * time.Second,
|
|
|
|
Timeout: time.Second,
|
|
|
|
PortLabel: "x",
|
|
|
|
CheckRestart: &structs.CheckRestart{
|
|
|
|
Limit: 11,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "c2",
|
|
|
|
Type: "http",
|
|
|
|
Path: "/",
|
|
|
|
Interval: time.Second,
|
|
|
|
Timeout: time.Second,
|
|
|
|
PortLabel: "x",
|
|
|
|
},
|
|
|
|
}
|
2019-11-18 18:04:01 +00:00
|
|
|
if err := ctx.ServiceClient.UpdateWorkload(origWorkload, ctx.Workload); err != nil {
|
2017-09-14 22:17:21 +00:00
|
|
|
t.Fatalf("unexpected error registering task: %v", err)
|
|
|
|
}
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
if err := ctx.syncOnce(syncNewOps); err != nil {
|
2017-09-14 22:17:21 +00:00
|
|
|
t.Fatalf("unexpected error syncing task: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if n := len(ctx.FakeConsul.checks); n != 2 {
|
|
|
|
t.Fatalf("expected 2 check but found %d:\n%#v", n, ctx.FakeConsul.checks)
|
|
|
|
}
|
|
|
|
|
|
|
|
for k, v := range ctx.FakeConsul.checks {
|
|
|
|
if v.Name == "c1" {
|
|
|
|
if k != c1ID {
|
|
|
|
t.Errorf("expected c1 to still have id %q but found %q", c1ID, k)
|
|
|
|
}
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Assert a check restart watch update was enqueued for a removal and an add
|
|
|
|
if n := len(ctx.ServiceClient.checkWatcher.checkUpdateCh); n != 1 {
|
|
|
|
t.Fatalf("expected 1 check restart update but found %d", n)
|
|
|
|
}
|
|
|
|
<-ctx.ServiceClient.checkWatcher.checkUpdateCh
|
2017-06-16 23:35:16 +00:00
|
|
|
}
|
|
|
|
|
2017-02-01 00:43:57 +00:00
|
|
|
// TestConsul_RegServices tests basic service registration.
|
|
|
|
func TestConsul_RegServices(t *testing.T) {
|
2018-04-17 19:36:50 +00:00
|
|
|
ctx := setupFake(t)
|
2017-02-01 00:43:57 +00:00
|
|
|
|
2017-09-14 22:17:21 +00:00
|
|
|
// Add a check w/restarting
|
2019-11-18 18:04:01 +00:00
|
|
|
ctx.Workload.Services[0].Checks = []*structs.ServiceCheck{
|
2017-09-14 22:17:21 +00:00
|
|
|
{
|
|
|
|
Name: "testcheck",
|
|
|
|
Type: "tcp",
|
|
|
|
Interval: 100 * time.Millisecond,
|
|
|
|
CheckRestart: &structs.CheckRestart{
|
|
|
|
Limit: 3,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
if err := ctx.ServiceClient.RegisterWorkload(ctx.Workload); err != nil {
|
2017-02-01 00:43:57 +00:00
|
|
|
t.Fatalf("unexpected error registering task: %v", err)
|
|
|
|
}
|
|
|
|
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
if err := ctx.syncOnce(syncNewOps); err != nil {
|
2017-02-01 00:43:57 +00:00
|
|
|
t.Fatalf("unexpected error syncing task: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if n := len(ctx.FakeConsul.services); n != 1 {
|
|
|
|
t.Fatalf("expected 1 service but found %d:\n%#v", n, ctx.FakeConsul.services)
|
|
|
|
}
|
2017-09-14 22:17:21 +00:00
|
|
|
|
2017-02-01 00:43:57 +00:00
|
|
|
for _, v := range ctx.FakeConsul.services {
|
2019-11-18 18:04:01 +00:00
|
|
|
if v.Name != ctx.Workload.Services[0].Name {
|
|
|
|
t.Errorf("expected Name=%q != %q", ctx.Workload.Services[0].Name, v.Name)
|
2017-02-01 00:43:57 +00:00
|
|
|
}
|
2019-11-18 18:04:01 +00:00
|
|
|
if !reflect.DeepEqual(v.Tags, ctx.Workload.Services[0].Tags) {
|
|
|
|
t.Errorf("expected Tags=%v != %v", ctx.Workload.Services[0].Tags, v.Tags)
|
2017-02-01 00:43:57 +00:00
|
|
|
}
|
2017-04-19 19:18:06 +00:00
|
|
|
if v.Port != xPort {
|
|
|
|
t.Errorf("expected Port=%d != %d", xPort, v.Port)
|
2017-02-01 00:43:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-14 22:17:21 +00:00
|
|
|
// Assert the check update is pending
|
|
|
|
if n := len(ctx.ServiceClient.checkWatcher.checkUpdateCh); n != 1 {
|
|
|
|
t.Fatalf("expected 1 check restart update but found %d", n)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Assert the check update is properly formed
|
|
|
|
checkUpd := <-ctx.ServiceClient.checkWatcher.checkUpdateCh
|
2019-11-18 18:04:01 +00:00
|
|
|
if checkUpd.checkRestart.allocID != ctx.Workload.AllocID {
|
2017-09-14 22:17:21 +00:00
|
|
|
t.Fatalf("expected check's allocid to be %q but found %q", "allocid", checkUpd.checkRestart.allocID)
|
|
|
|
}
|
|
|
|
if expected := 200 * time.Millisecond; checkUpd.checkRestart.timeLimit != expected {
|
|
|
|
t.Fatalf("expected check's time limit to be %v but found %v", expected, checkUpd.checkRestart.timeLimit)
|
|
|
|
}
|
|
|
|
|
2017-02-01 00:43:57 +00:00
|
|
|
// Make a change which will register a new service
|
2019-11-18 18:04:01 +00:00
|
|
|
ctx.Workload.Services[0].Name = "taskname-service2"
|
|
|
|
ctx.Workload.Services[0].Tags[0] = "tag3"
|
|
|
|
if err := ctx.ServiceClient.RegisterWorkload(ctx.Workload); err != nil {
|
2018-03-11 19:08:07 +00:00
|
|
|
t.Fatalf("unexpected error registering task: %v", err)
|
2017-02-01 00:43:57 +00:00
|
|
|
}
|
|
|
|
|
2017-09-14 22:17:21 +00:00
|
|
|
// Assert check update is pending
|
|
|
|
if n := len(ctx.ServiceClient.checkWatcher.checkUpdateCh); n != 1 {
|
|
|
|
t.Fatalf("expected 1 check restart update but found %d", n)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Assert the check update's id has changed
|
|
|
|
checkUpd2 := <-ctx.ServiceClient.checkWatcher.checkUpdateCh
|
|
|
|
if checkUpd.checkID == checkUpd2.checkID {
|
|
|
|
t.Fatalf("expected new check update to have a new ID both both have: %q", checkUpd.checkID)
|
|
|
|
}
|
|
|
|
|
2017-02-01 00:43:57 +00:00
|
|
|
// Make sure changes don't take affect until sync() is called (since
|
|
|
|
// Run() isn't running)
|
|
|
|
if n := len(ctx.FakeConsul.services); n != 1 {
|
|
|
|
t.Fatalf("expected 1 service but found %d:\n%#v", n, ctx.FakeConsul.services)
|
|
|
|
}
|
|
|
|
for _, v := range ctx.FakeConsul.services {
|
2019-11-18 18:04:01 +00:00
|
|
|
if reflect.DeepEqual(v.Tags, ctx.Workload.Services[0].Tags) {
|
2017-02-01 00:43:57 +00:00
|
|
|
t.Errorf("expected Tags to differ, changes applied before sync()")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now sync() and re-check for the applied updates
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
if err := ctx.syncOnce(syncNewOps); err != nil {
|
2017-02-01 00:43:57 +00:00
|
|
|
t.Fatalf("unexpected error syncing task: %v", err)
|
|
|
|
}
|
|
|
|
if n := len(ctx.FakeConsul.services); n != 2 {
|
|
|
|
t.Fatalf("expected 2 services but found %d:\n%#v", n, ctx.FakeConsul.services)
|
|
|
|
}
|
|
|
|
found := false
|
|
|
|
for _, v := range ctx.FakeConsul.services {
|
2019-11-18 18:04:01 +00:00
|
|
|
if v.Name == ctx.Workload.Services[0].Name {
|
2017-02-01 00:43:57 +00:00
|
|
|
if found {
|
|
|
|
t.Fatalf("found new service name %q twice", v.Name)
|
|
|
|
}
|
|
|
|
found = true
|
2019-11-18 18:04:01 +00:00
|
|
|
if !reflect.DeepEqual(v.Tags, ctx.Workload.Services[0].Tags) {
|
|
|
|
t.Errorf("expected Tags=%v != %v", ctx.Workload.Services[0].Tags, v.Tags)
|
2017-02-01 00:43:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !found {
|
2019-11-18 18:04:01 +00:00
|
|
|
t.Fatalf("did not find new service %q", ctx.Workload.Services[0].Name)
|
2017-02-01 00:43:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Remove the new task
|
2019-11-18 18:04:01 +00:00
|
|
|
ctx.ServiceClient.RemoveWorkload(ctx.Workload)
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
if err := ctx.syncOnce(syncNewOps); err != nil {
|
2017-02-01 00:43:57 +00:00
|
|
|
t.Fatalf("unexpected error syncing task: %v", err)
|
|
|
|
}
|
|
|
|
if n := len(ctx.FakeConsul.services); n != 1 {
|
|
|
|
t.Fatalf("expected 1 service but found %d:\n%#v", n, ctx.FakeConsul.services)
|
|
|
|
}
|
|
|
|
for _, v := range ctx.FakeConsul.services {
|
|
|
|
if v.Name != "taskname-service" {
|
|
|
|
t.Errorf("expected original task to survive not %q", v.Name)
|
|
|
|
}
|
|
|
|
}
|
2017-09-14 22:17:21 +00:00
|
|
|
|
|
|
|
// Assert check update is pending
|
|
|
|
if n := len(ctx.ServiceClient.checkWatcher.checkUpdateCh); n != 1 {
|
|
|
|
t.Fatalf("expected 1 check restart update but found %d", n)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Assert the check update's id is correct and that it's a removal
|
|
|
|
checkUpd3 := <-ctx.ServiceClient.checkWatcher.checkUpdateCh
|
|
|
|
if checkUpd2.checkID != checkUpd3.checkID {
|
|
|
|
t.Fatalf("expected checkid %q but found %q", checkUpd2.checkID, checkUpd3.checkID)
|
|
|
|
}
|
|
|
|
if !checkUpd3.remove {
|
|
|
|
t.Fatalf("expected check watch removal update but found: %#v", checkUpd3)
|
|
|
|
}
|
2017-02-01 00:43:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// TestConsul_ShutdownOK tests the ok path for the shutdown logic in
|
|
|
|
// ServiceClient.
|
|
|
|
func TestConsul_ShutdownOK(t *testing.T) {
|
2018-03-15 00:37:54 +00:00
|
|
|
require := require.New(t)
|
2018-04-17 19:36:50 +00:00
|
|
|
ctx := setupFake(t)
|
2017-04-08 00:10:26 +00:00
|
|
|
go ctx.ServiceClient.Run()
|
2017-02-01 00:43:57 +00:00
|
|
|
|
support script checks for task group services (#6197)
In Nomad prior to Consul Connect, all Consul checks work the same
except for Script checks. Because the Task being checked is running in
its own container namespaces, the check is executed by Nomad in the
Task's context. If the Script check passes, Nomad uses the TTL check
feature of Consul to update the check status. This means in order to
run a Script check, we need to know what Task to execute it in.
To support Consul Connect, we need Group Services, and these need to
be registered in Consul along with their checks. We could push the
Service down into the Task, but this doesn't work if someone wants to
associate a service with a task's ports, but do script checks in
another task in the allocation.
Because Nomad is handling the Script check and not Consul anyways,
this moves the script check handling into the task runner so that the
task runner can own the script check's configuration and
lifecycle. This will allow us to pass the group service check
configuration down into a task without associating the service itself
with the task.
When tasks are checked for script checks, we walk back through their
task group to see if there are script checks associated with the
task. If so, we'll spin off script check tasklets for them. The
group-level service and any restart behaviors it needs are entirely
encapsulated within the group service hook.
2019-09-03 19:09:04 +00:00
|
|
|
// register the Nomad agent service and check
|
2017-02-01 00:43:57 +00:00
|
|
|
agentServices := []*structs.Service{
|
|
|
|
{
|
|
|
|
Name: "http",
|
|
|
|
Tags: []string{"nomad"},
|
|
|
|
PortLabel: "localhost:2345",
|
support script checks for task group services (#6197)
In Nomad prior to Consul Connect, all Consul checks work the same
except for Script checks. Because the Task being checked is running in
its own container namespaces, the check is executed by Nomad in the
Task's context. If the Script check passes, Nomad uses the TTL check
feature of Consul to update the check status. This means in order to
run a Script check, we need to know what Task to execute it in.
To support Consul Connect, we need Group Services, and these need to
be registered in Consul along with their checks. We could push the
Service down into the Task, but this doesn't work if someone wants to
associate a service with a task's ports, but do script checks in
another task in the allocation.
Because Nomad is handling the Script check and not Consul anyways,
this moves the script check handling into the task runner so that the
task runner can own the script check's configuration and
lifecycle. This will allow us to pass the group service check
configuration down into a task without associating the service itself
with the task.
When tasks are checked for script checks, we walk back through their
task group to see if there are script checks associated with the
task. If so, we'll spin off script check tasklets for them. The
group-level service and any restart behaviors it needs are entirely
encapsulated within the group service hook.
2019-09-03 19:09:04 +00:00
|
|
|
Checks: []*structs.ServiceCheck{
|
|
|
|
{
|
|
|
|
Name: "nomad-tcp",
|
|
|
|
Type: "tcp",
|
|
|
|
Interval: 9000 * time.Hour, // make check block
|
|
|
|
Timeout: 10 * time.Second,
|
|
|
|
InitialStatus: "warning",
|
|
|
|
},
|
|
|
|
},
|
2017-02-01 00:43:57 +00:00
|
|
|
},
|
|
|
|
}
|
support script checks for task group services (#6197)
In Nomad prior to Consul Connect, all Consul checks work the same
except for Script checks. Because the Task being checked is running in
its own container namespaces, the check is executed by Nomad in the
Task's context. If the Script check passes, Nomad uses the TTL check
feature of Consul to update the check status. This means in order to
run a Script check, we need to know what Task to execute it in.
To support Consul Connect, we need Group Services, and these need to
be registered in Consul along with their checks. We could push the
Service down into the Task, but this doesn't work if someone wants to
associate a service with a task's ports, but do script checks in
another task in the allocation.
Because Nomad is handling the Script check and not Consul anyways,
this moves the script check handling into the task runner so that the
task runner can own the script check's configuration and
lifecycle. This will allow us to pass the group service check
configuration down into a task without associating the service itself
with the task.
When tasks are checked for script checks, we walk back through their
task group to see if there are script checks associated with the
task. If so, we'll spin off script check tasklets for them. The
group-level service and any restart behaviors it needs are entirely
encapsulated within the group service hook.
2019-09-03 19:09:04 +00:00
|
|
|
require.NoError(ctx.ServiceClient.RegisterAgent("client", agentServices))
|
|
|
|
require.Eventually(ctx.ServiceClient.hasSeen, time.Second, 10*time.Millisecond)
|
2017-02-01 00:43:57 +00:00
|
|
|
|
support script checks for task group services (#6197)
In Nomad prior to Consul Connect, all Consul checks work the same
except for Script checks. Because the Task being checked is running in
its own container namespaces, the check is executed by Nomad in the
Task's context. If the Script check passes, Nomad uses the TTL check
feature of Consul to update the check status. This means in order to
run a Script check, we need to know what Task to execute it in.
To support Consul Connect, we need Group Services, and these need to
be registered in Consul along with their checks. We could push the
Service down into the Task, but this doesn't work if someone wants to
associate a service with a task's ports, but do script checks in
another task in the allocation.
Because Nomad is handling the Script check and not Consul anyways,
this moves the script check handling into the task runner so that the
task runner can own the script check's configuration and
lifecycle. This will allow us to pass the group service check
configuration down into a task without associating the service itself
with the task.
When tasks are checked for script checks, we walk back through their
task group to see if there are script checks associated with the
task. If so, we'll spin off script check tasklets for them. The
group-level service and any restart behaviors it needs are entirely
encapsulated within the group service hook.
2019-09-03 19:09:04 +00:00
|
|
|
// assert successful registration
|
|
|
|
require.Len(ctx.FakeConsul.services, 1, "expected agent service to be registered")
|
|
|
|
require.Len(ctx.FakeConsul.checks, 1, "expected agent check to be registered")
|
|
|
|
require.Contains(ctx.FakeConsul.services,
|
|
|
|
makeAgentServiceID("client", agentServices[0]))
|
2017-02-01 00:43:57 +00:00
|
|
|
|
support script checks for task group services (#6197)
In Nomad prior to Consul Connect, all Consul checks work the same
except for Script checks. Because the Task being checked is running in
its own container namespaces, the check is executed by Nomad in the
Task's context. If the Script check passes, Nomad uses the TTL check
feature of Consul to update the check status. This means in order to
run a Script check, we need to know what Task to execute it in.
To support Consul Connect, we need Group Services, and these need to
be registered in Consul along with their checks. We could push the
Service down into the Task, but this doesn't work if someone wants to
associate a service with a task's ports, but do script checks in
another task in the allocation.
Because Nomad is handling the Script check and not Consul anyways,
this moves the script check handling into the task runner so that the
task runner can own the script check's configuration and
lifecycle. This will allow us to pass the group service check
configuration down into a task without associating the service itself
with the task.
When tasks are checked for script checks, we walk back through their
task group to see if there are script checks associated with the
task. If so, we'll spin off script check tasklets for them. The
group-level service and any restart behaviors it needs are entirely
encapsulated within the group service hook.
2019-09-03 19:09:04 +00:00
|
|
|
// Shutdown() should block until Nomad agent service/check is deregistered
|
|
|
|
require.NoError(ctx.ServiceClient.Shutdown())
|
|
|
|
require.Len(ctx.FakeConsul.services, 0, "expected agent service to be deregistered")
|
|
|
|
require.Len(ctx.FakeConsul.checks, 0, "expected agent check to be deregistered")
|
2017-02-01 00:43:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// TestConsul_ShutdownBlocked tests the blocked past deadline path for the
|
|
|
|
// shutdown logic in ServiceClient.
|
|
|
|
func TestConsul_ShutdownBlocked(t *testing.T) {
|
support script checks for task group services (#6197)
In Nomad prior to Consul Connect, all Consul checks work the same
except for Script checks. Because the Task being checked is running in
its own container namespaces, the check is executed by Nomad in the
Task's context. If the Script check passes, Nomad uses the TTL check
feature of Consul to update the check status. This means in order to
run a Script check, we need to know what Task to execute it in.
To support Consul Connect, we need Group Services, and these need to
be registered in Consul along with their checks. We could push the
Service down into the Task, but this doesn't work if someone wants to
associate a service with a task's ports, but do script checks in
another task in the allocation.
Because Nomad is handling the Script check and not Consul anyways,
this moves the script check handling into the task runner so that the
task runner can own the script check's configuration and
lifecycle. This will allow us to pass the group service check
configuration down into a task without associating the service itself
with the task.
When tasks are checked for script checks, we walk back through their
task group to see if there are script checks associated with the
task. If so, we'll spin off script check tasklets for them. The
group-level service and any restart behaviors it needs are entirely
encapsulated within the group service hook.
2019-09-03 19:09:04 +00:00
|
|
|
require := require.New(t)
|
2018-04-17 19:36:50 +00:00
|
|
|
t.Parallel()
|
|
|
|
ctx := setupFake(t)
|
support script checks for task group services (#6197)
In Nomad prior to Consul Connect, all Consul checks work the same
except for Script checks. Because the Task being checked is running in
its own container namespaces, the check is executed by Nomad in the
Task's context. If the Script check passes, Nomad uses the TTL check
feature of Consul to update the check status. This means in order to
run a Script check, we need to know what Task to execute it in.
To support Consul Connect, we need Group Services, and these need to
be registered in Consul along with their checks. We could push the
Service down into the Task, but this doesn't work if someone wants to
associate a service with a task's ports, but do script checks in
another task in the allocation.
Because Nomad is handling the Script check and not Consul anyways,
this moves the script check handling into the task runner so that the
task runner can own the script check's configuration and
lifecycle. This will allow us to pass the group service check
configuration down into a task without associating the service itself
with the task.
When tasks are checked for script checks, we walk back through their
task group to see if there are script checks associated with the
task. If so, we'll spin off script check tasklets for them. The
group-level service and any restart behaviors it needs are entirely
encapsulated within the group service hook.
2019-09-03 19:09:04 +00:00
|
|
|
// can be short because we're intentionally blocking, but needs to
|
|
|
|
// be longer than the time we'll block Consul so we can be sure
|
|
|
|
// we're not delayed either.
|
|
|
|
ctx.ServiceClient.shutdownWait = time.Second
|
|
|
|
go ctx.ServiceClient.Run()
|
2017-02-01 00:43:57 +00:00
|
|
|
|
support script checks for task group services (#6197)
In Nomad prior to Consul Connect, all Consul checks work the same
except for Script checks. Because the Task being checked is running in
its own container namespaces, the check is executed by Nomad in the
Task's context. If the Script check passes, Nomad uses the TTL check
feature of Consul to update the check status. This means in order to
run a Script check, we need to know what Task to execute it in.
To support Consul Connect, we need Group Services, and these need to
be registered in Consul along with their checks. We could push the
Service down into the Task, but this doesn't work if someone wants to
associate a service with a task's ports, but do script checks in
another task in the allocation.
Because Nomad is handling the Script check and not Consul anyways,
this moves the script check handling into the task runner so that the
task runner can own the script check's configuration and
lifecycle. This will allow us to pass the group service check
configuration down into a task without associating the service itself
with the task.
When tasks are checked for script checks, we walk back through their
task group to see if there are script checks associated with the
task. If so, we'll spin off script check tasklets for them. The
group-level service and any restart behaviors it needs are entirely
encapsulated within the group service hook.
2019-09-03 19:09:04 +00:00
|
|
|
// register the Nomad agent service and check
|
|
|
|
agentServices := []*structs.Service{
|
2017-02-01 00:43:57 +00:00
|
|
|
{
|
support script checks for task group services (#6197)
In Nomad prior to Consul Connect, all Consul checks work the same
except for Script checks. Because the Task being checked is running in
its own container namespaces, the check is executed by Nomad in the
Task's context. If the Script check passes, Nomad uses the TTL check
feature of Consul to update the check status. This means in order to
run a Script check, we need to know what Task to execute it in.
To support Consul Connect, we need Group Services, and these need to
be registered in Consul along with their checks. We could push the
Service down into the Task, but this doesn't work if someone wants to
associate a service with a task's ports, but do script checks in
another task in the allocation.
Because Nomad is handling the Script check and not Consul anyways,
this moves the script check handling into the task runner so that the
task runner can own the script check's configuration and
lifecycle. This will allow us to pass the group service check
configuration down into a task without associating the service itself
with the task.
When tasks are checked for script checks, we walk back through their
task group to see if there are script checks associated with the
task. If so, we'll spin off script check tasklets for them. The
group-level service and any restart behaviors it needs are entirely
encapsulated within the group service hook.
2019-09-03 19:09:04 +00:00
|
|
|
Name: "http",
|
|
|
|
Tags: []string{"nomad"},
|
|
|
|
PortLabel: "localhost:2345",
|
|
|
|
Checks: []*structs.ServiceCheck{
|
|
|
|
{
|
|
|
|
Name: "nomad-tcp",
|
|
|
|
Type: "tcp",
|
|
|
|
Interval: 9000 * time.Hour, // make check block
|
|
|
|
Timeout: 10 * time.Second,
|
|
|
|
InitialStatus: "warning",
|
|
|
|
},
|
|
|
|
},
|
2017-02-01 00:43:57 +00:00
|
|
|
},
|
|
|
|
}
|
support script checks for task group services (#6197)
In Nomad prior to Consul Connect, all Consul checks work the same
except for Script checks. Because the Task being checked is running in
its own container namespaces, the check is executed by Nomad in the
Task's context. If the Script check passes, Nomad uses the TTL check
feature of Consul to update the check status. This means in order to
run a Script check, we need to know what Task to execute it in.
To support Consul Connect, we need Group Services, and these need to
be registered in Consul along with their checks. We could push the
Service down into the Task, but this doesn't work if someone wants to
associate a service with a task's ports, but do script checks in
another task in the allocation.
Because Nomad is handling the Script check and not Consul anyways,
this moves the script check handling into the task runner so that the
task runner can own the script check's configuration and
lifecycle. This will allow us to pass the group service check
configuration down into a task without associating the service itself
with the task.
When tasks are checked for script checks, we walk back through their
task group to see if there are script checks associated with the
task. If so, we'll spin off script check tasklets for them. The
group-level service and any restart behaviors it needs are entirely
encapsulated within the group service hook.
2019-09-03 19:09:04 +00:00
|
|
|
require.NoError(ctx.ServiceClient.RegisterAgent("client", agentServices))
|
|
|
|
require.Eventually(ctx.ServiceClient.hasSeen, time.Second, 10*time.Millisecond)
|
|
|
|
require.Len(ctx.FakeConsul.services, 1, "expected agent service to be registered")
|
|
|
|
require.Len(ctx.FakeConsul.checks, 1, "expected agent check to be registered")
|
2017-02-01 00:43:57 +00:00
|
|
|
|
support script checks for task group services (#6197)
In Nomad prior to Consul Connect, all Consul checks work the same
except for Script checks. Because the Task being checked is running in
its own container namespaces, the check is executed by Nomad in the
Task's context. If the Script check passes, Nomad uses the TTL check
feature of Consul to update the check status. This means in order to
run a Script check, we need to know what Task to execute it in.
To support Consul Connect, we need Group Services, and these need to
be registered in Consul along with their checks. We could push the
Service down into the Task, but this doesn't work if someone wants to
associate a service with a task's ports, but do script checks in
another task in the allocation.
Because Nomad is handling the Script check and not Consul anyways,
this moves the script check handling into the task runner so that the
task runner can own the script check's configuration and
lifecycle. This will allow us to pass the group service check
configuration down into a task without associating the service itself
with the task.
When tasks are checked for script checks, we walk back through their
task group to see if there are script checks associated with the
task. If so, we'll spin off script check tasklets for them. The
group-level service and any restart behaviors it needs are entirely
encapsulated within the group service hook.
2019-09-03 19:09:04 +00:00
|
|
|
// prevent normal shutdown by blocking Consul. the shutdown should wait
|
|
|
|
// until agent deregistration has finished
|
2017-04-08 00:10:26 +00:00
|
|
|
waiter := make(chan struct{})
|
support script checks for task group services (#6197)
In Nomad prior to Consul Connect, all Consul checks work the same
except for Script checks. Because the Task being checked is running in
its own container namespaces, the check is executed by Nomad in the
Task's context. If the Script check passes, Nomad uses the TTL check
feature of Consul to update the check status. This means in order to
run a Script check, we need to know what Task to execute it in.
To support Consul Connect, we need Group Services, and these need to
be registered in Consul along with their checks. We could push the
Service down into the Task, but this doesn't work if someone wants to
associate a service with a task's ports, but do script checks in
another task in the allocation.
Because Nomad is handling the Script check and not Consul anyways,
this moves the script check handling into the task runner so that the
task runner can own the script check's configuration and
lifecycle. This will allow us to pass the group service check
configuration down into a task without associating the service itself
with the task.
When tasks are checked for script checks, we walk back through their
task group to see if there are script checks associated with the
task. If so, we'll spin off script check tasklets for them. The
group-level service and any restart behaviors it needs are entirely
encapsulated within the group service hook.
2019-09-03 19:09:04 +00:00
|
|
|
result := make(chan error)
|
|
|
|
go func() {
|
|
|
|
ctx.FakeConsul.mu.Lock()
|
2017-04-08 00:10:26 +00:00
|
|
|
close(waiter)
|
support script checks for task group services (#6197)
In Nomad prior to Consul Connect, all Consul checks work the same
except for Script checks. Because the Task being checked is running in
its own container namespaces, the check is executed by Nomad in the
Task's context. If the Script check passes, Nomad uses the TTL check
feature of Consul to update the check status. This means in order to
run a Script check, we need to know what Task to execute it in.
To support Consul Connect, we need Group Services, and these need to
be registered in Consul along with their checks. We could push the
Service down into the Task, but this doesn't work if someone wants to
associate a service with a task's ports, but do script checks in
another task in the allocation.
Because Nomad is handling the Script check and not Consul anyways,
this moves the script check handling into the task runner so that the
task runner can own the script check's configuration and
lifecycle. This will allow us to pass the group service check
configuration down into a task without associating the service itself
with the task.
When tasks are checked for script checks, we walk back through their
task group to see if there are script checks associated with the
task. If so, we'll spin off script check tasklets for them. The
group-level service and any restart behaviors it needs are entirely
encapsulated within the group service hook.
2019-09-03 19:09:04 +00:00
|
|
|
result <- ctx.ServiceClient.Shutdown()
|
|
|
|
}()
|
2017-02-01 00:43:57 +00:00
|
|
|
|
support script checks for task group services (#6197)
In Nomad prior to Consul Connect, all Consul checks work the same
except for Script checks. Because the Task being checked is running in
its own container namespaces, the check is executed by Nomad in the
Task's context. If the Script check passes, Nomad uses the TTL check
feature of Consul to update the check status. This means in order to
run a Script check, we need to know what Task to execute it in.
To support Consul Connect, we need Group Services, and these need to
be registered in Consul along with their checks. We could push the
Service down into the Task, but this doesn't work if someone wants to
associate a service with a task's ports, but do script checks in
another task in the allocation.
Because Nomad is handling the Script check and not Consul anyways,
this moves the script check handling into the task runner so that the
task runner can own the script check's configuration and
lifecycle. This will allow us to pass the group service check
configuration down into a task without associating the service itself
with the task.
When tasks are checked for script checks, we walk back through their
task group to see if there are script checks associated with the
task. If so, we'll spin off script check tasklets for them. The
group-level service and any restart behaviors it needs are entirely
encapsulated within the group service hook.
2019-09-03 19:09:04 +00:00
|
|
|
<-waiter // wait for lock to be hit
|
2017-04-08 00:10:26 +00:00
|
|
|
|
2017-02-01 00:43:57 +00:00
|
|
|
// Shutdown should block until all enqueued operations finish.
|
|
|
|
preShutdown := time.Now()
|
2017-04-26 18:22:01 +00:00
|
|
|
select {
|
support script checks for task group services (#6197)
In Nomad prior to Consul Connect, all Consul checks work the same
except for Script checks. Because the Task being checked is running in
its own container namespaces, the check is executed by Nomad in the
Task's context. If the Script check passes, Nomad uses the TTL check
feature of Consul to update the check status. This means in order to
run a Script check, we need to know what Task to execute it in.
To support Consul Connect, we need Group Services, and these need to
be registered in Consul along with their checks. We could push the
Service down into the Task, but this doesn't work if someone wants to
associate a service with a task's ports, but do script checks in
another task in the allocation.
Because Nomad is handling the Script check and not Consul anyways,
this moves the script check handling into the task runner so that the
task runner can own the script check's configuration and
lifecycle. This will allow us to pass the group service check
configuration down into a task without associating the service itself
with the task.
When tasks are checked for script checks, we walk back through their
task group to see if there are script checks associated with the
task. If so, we'll spin off script check tasklets for them. The
group-level service and any restart behaviors it needs are entirely
encapsulated within the group service hook.
2019-09-03 19:09:04 +00:00
|
|
|
case <-time.After(200 * time.Millisecond):
|
|
|
|
ctx.FakeConsul.mu.Unlock()
|
|
|
|
require.NoError(<-result)
|
|
|
|
case <-result:
|
|
|
|
t.Fatal("should not have received result until Consul unblocked")
|
|
|
|
}
|
|
|
|
shutdownTime := time.Now().Sub(preShutdown).Seconds()
|
|
|
|
require.Less(shutdownTime, time.Second.Seconds(),
|
|
|
|
"expected shutdown to take >200ms and <1s")
|
|
|
|
require.Greater(shutdownTime, 200*time.Millisecond.Seconds(),
|
|
|
|
"expected shutdown to take >200ms and <1s")
|
|
|
|
require.Len(ctx.FakeConsul.services, 0,
|
|
|
|
"expected agent service to be deregistered")
|
|
|
|
require.Len(ctx.FakeConsul.checks, 0,
|
|
|
|
"expected agent check to be deregistered")
|
2017-04-26 18:22:01 +00:00
|
|
|
}
|
2017-06-13 21:02:11 +00:00
|
|
|
|
|
|
|
// TestConsul_DriverNetwork_AutoUse asserts that if a driver network has
|
|
|
|
// auto-use set then services should advertise it unless explicitly set to
|
|
|
|
// host. Checks should always use host.
|
|
|
|
func TestConsul_DriverNetwork_AutoUse(t *testing.T) {
|
2018-04-17 19:36:50 +00:00
|
|
|
t.Parallel()
|
|
|
|
ctx := setupFake(t)
|
2017-06-13 21:02:11 +00:00
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
ctx.Workload.Services = []*structs.Service{
|
2017-06-13 21:02:11 +00:00
|
|
|
{
|
|
|
|
Name: "auto-advertise-x",
|
|
|
|
PortLabel: "x",
|
|
|
|
AddressMode: structs.AddressModeAuto,
|
|
|
|
Checks: []*structs.ServiceCheck{
|
|
|
|
{
|
|
|
|
Name: "default-check-x",
|
|
|
|
Type: "tcp",
|
|
|
|
Interval: time.Second,
|
|
|
|
Timeout: time.Second,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "weird-y-check",
|
2017-06-16 23:35:16 +00:00
|
|
|
Type: "http",
|
2017-06-13 21:02:11 +00:00
|
|
|
Interval: time.Second,
|
|
|
|
Timeout: time.Second,
|
|
|
|
PortLabel: "y",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "driver-advertise-y",
|
|
|
|
PortLabel: "y",
|
|
|
|
AddressMode: structs.AddressModeDriver,
|
|
|
|
Checks: []*structs.ServiceCheck{
|
|
|
|
{
|
|
|
|
Name: "default-check-y",
|
|
|
|
Type: "tcp",
|
|
|
|
Interval: time.Second,
|
|
|
|
Timeout: time.Second,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "host-advertise-y",
|
|
|
|
PortLabel: "y",
|
|
|
|
AddressMode: structs.AddressModeHost,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
ctx.Workload.DriverNetwork = &drivers.DriverNetwork{
|
2017-06-13 21:02:11 +00:00
|
|
|
PortMap: map[string]int{
|
|
|
|
"x": 8888,
|
|
|
|
"y": 9999,
|
|
|
|
},
|
2017-06-16 23:35:16 +00:00
|
|
|
IP: "172.18.0.2",
|
|
|
|
AutoAdvertise: true,
|
2017-06-13 21:02:11 +00:00
|
|
|
}
|
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
if err := ctx.ServiceClient.RegisterWorkload(ctx.Workload); err != nil {
|
2017-06-13 21:02:11 +00:00
|
|
|
t.Fatalf("unexpected error registering task: %v", err)
|
|
|
|
}
|
|
|
|
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
if err := ctx.syncOnce(syncNewOps); err != nil {
|
2017-06-13 21:02:11 +00:00
|
|
|
t.Fatalf("unexpected error syncing task: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if n := len(ctx.FakeConsul.services); n != 3 {
|
|
|
|
t.Fatalf("expected 2 services but found: %d", n)
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, v := range ctx.FakeConsul.services {
|
|
|
|
switch v.Name {
|
2019-11-18 18:04:01 +00:00
|
|
|
case ctx.Workload.Services[0].Name: // x
|
2017-06-16 23:35:16 +00:00
|
|
|
// Since DriverNetwork.AutoAdvertise=true, driver ports should be used
|
2019-11-18 18:04:01 +00:00
|
|
|
if v.Port != ctx.Workload.DriverNetwork.PortMap["x"] {
|
2017-06-13 21:02:11 +00:00
|
|
|
t.Errorf("expected service %s's port to be %d but found %d",
|
2019-11-18 18:04:01 +00:00
|
|
|
v.Name, ctx.Workload.DriverNetwork.PortMap["x"], v.Port)
|
2017-06-13 21:02:11 +00:00
|
|
|
}
|
2017-06-16 23:35:16 +00:00
|
|
|
// The order of checks in Consul is not guaranteed to
|
2019-11-18 18:04:01 +00:00
|
|
|
// be the same as their order in the Workload definition,
|
2017-06-16 23:35:16 +00:00
|
|
|
// so check in a loop
|
|
|
|
if expected := 2; len(v.Checks) != expected {
|
2017-06-26 19:53:43 +00:00
|
|
|
t.Errorf("expected %d checks but found %d", expected, len(v.Checks))
|
2017-06-13 21:02:11 +00:00
|
|
|
}
|
2017-06-16 23:35:16 +00:00
|
|
|
for _, c := range v.Checks {
|
|
|
|
// No name on AgentServiceChecks, use type
|
|
|
|
switch {
|
|
|
|
case c.TCP != "":
|
|
|
|
// Checks should always use host port though
|
|
|
|
if c.TCP != ":1234" { // xPort
|
2018-03-11 17:57:01 +00:00
|
|
|
t.Errorf("expected service %s check 1's port to be %d but found %q",
|
2017-06-16 23:35:16 +00:00
|
|
|
v.Name, xPort, c.TCP)
|
|
|
|
}
|
|
|
|
case c.HTTP != "":
|
|
|
|
if c.HTTP != "http://:1235" { // yPort
|
2018-03-11 17:57:01 +00:00
|
|
|
t.Errorf("expected service %s check 2's port to be %d but found %q",
|
2017-06-16 23:35:16 +00:00
|
|
|
v.Name, yPort, c.HTTP)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
t.Errorf("unexpected check %#v on service %q", c, v.Name)
|
|
|
|
}
|
2017-06-13 21:02:11 +00:00
|
|
|
}
|
2019-11-18 18:04:01 +00:00
|
|
|
case ctx.Workload.Services[1].Name: // y
|
2017-06-13 21:02:11 +00:00
|
|
|
// Service should be container ip:port
|
2019-11-18 18:04:01 +00:00
|
|
|
if v.Address != ctx.Workload.DriverNetwork.IP {
|
2017-06-13 21:02:11 +00:00
|
|
|
t.Errorf("expected service %s's address to be %s but found %s",
|
2019-11-18 18:04:01 +00:00
|
|
|
v.Name, ctx.Workload.DriverNetwork.IP, v.Address)
|
2017-06-13 21:02:11 +00:00
|
|
|
}
|
2019-11-18 18:04:01 +00:00
|
|
|
if v.Port != ctx.Workload.DriverNetwork.PortMap["y"] {
|
2017-06-13 21:02:11 +00:00
|
|
|
t.Errorf("expected service %s's port to be %d but found %d",
|
2019-11-18 18:04:01 +00:00
|
|
|
v.Name, ctx.Workload.DriverNetwork.PortMap["x"], v.Port)
|
2017-06-13 21:02:11 +00:00
|
|
|
}
|
|
|
|
// Check should be host ip:port
|
|
|
|
if v.Checks[0].TCP != ":1235" { // yPort
|
|
|
|
t.Errorf("expected service %s check's port to be %d but found %s",
|
|
|
|
v.Name, yPort, v.Checks[0].TCP)
|
|
|
|
}
|
2019-11-18 18:04:01 +00:00
|
|
|
case ctx.Workload.Services[2].Name: // y + host mode
|
2017-06-13 21:02:11 +00:00
|
|
|
if v.Port != yPort {
|
2017-06-26 19:53:43 +00:00
|
|
|
t.Errorf("expected service %s's port to be %d but found %d",
|
2017-06-13 21:02:11 +00:00
|
|
|
v.Name, yPort, v.Port)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
t.Errorf("unexpected service name: %q", v.Name)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// TestConsul_DriverNetwork_NoAutoUse asserts that if a driver network doesn't
|
|
|
|
// set auto-use only services which request the driver's network should
|
|
|
|
// advertise it.
|
|
|
|
func TestConsul_DriverNetwork_NoAutoUse(t *testing.T) {
|
2018-04-17 19:36:50 +00:00
|
|
|
t.Parallel()
|
|
|
|
ctx := setupFake(t)
|
2017-06-13 21:02:11 +00:00
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
ctx.Workload.Services = []*structs.Service{
|
2017-06-13 21:02:11 +00:00
|
|
|
{
|
|
|
|
Name: "auto-advertise-x",
|
|
|
|
PortLabel: "x",
|
|
|
|
AddressMode: structs.AddressModeAuto,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "driver-advertise-y",
|
|
|
|
PortLabel: "y",
|
|
|
|
AddressMode: structs.AddressModeDriver,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "host-advertise-y",
|
|
|
|
PortLabel: "y",
|
|
|
|
AddressMode: structs.AddressModeHost,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
ctx.Workload.DriverNetwork = &drivers.DriverNetwork{
|
2017-06-13 21:02:11 +00:00
|
|
|
PortMap: map[string]int{
|
|
|
|
"x": 8888,
|
|
|
|
"y": 9999,
|
|
|
|
},
|
2017-06-16 23:35:16 +00:00
|
|
|
IP: "172.18.0.2",
|
|
|
|
AutoAdvertise: false,
|
2017-06-13 21:02:11 +00:00
|
|
|
}
|
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
if err := ctx.ServiceClient.RegisterWorkload(ctx.Workload); err != nil {
|
2017-06-13 21:02:11 +00:00
|
|
|
t.Fatalf("unexpected error registering task: %v", err)
|
|
|
|
}
|
|
|
|
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
if err := ctx.syncOnce(syncNewOps); err != nil {
|
2017-06-13 21:02:11 +00:00
|
|
|
t.Fatalf("unexpected error syncing task: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if n := len(ctx.FakeConsul.services); n != 3 {
|
2017-06-16 23:35:16 +00:00
|
|
|
t.Fatalf("expected 3 services but found: %d", n)
|
2017-06-13 21:02:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, v := range ctx.FakeConsul.services {
|
|
|
|
switch v.Name {
|
2019-11-18 18:04:01 +00:00
|
|
|
case ctx.Workload.Services[0].Name: // x + auto
|
2017-06-16 23:35:16 +00:00
|
|
|
// Since DriverNetwork.AutoAdvertise=false, host ports should be used
|
2017-06-13 21:02:11 +00:00
|
|
|
if v.Port != xPort {
|
|
|
|
t.Errorf("expected service %s's port to be %d but found %d",
|
|
|
|
v.Name, xPort, v.Port)
|
|
|
|
}
|
2019-11-18 18:04:01 +00:00
|
|
|
case ctx.Workload.Services[1].Name: // y + driver mode
|
2017-06-13 21:02:11 +00:00
|
|
|
// Service should be container ip:port
|
2019-11-18 18:04:01 +00:00
|
|
|
if v.Address != ctx.Workload.DriverNetwork.IP {
|
2017-06-13 21:02:11 +00:00
|
|
|
t.Errorf("expected service %s's address to be %s but found %s",
|
2019-11-18 18:04:01 +00:00
|
|
|
v.Name, ctx.Workload.DriverNetwork.IP, v.Address)
|
2017-06-13 21:02:11 +00:00
|
|
|
}
|
2019-11-18 18:04:01 +00:00
|
|
|
if v.Port != ctx.Workload.DriverNetwork.PortMap["y"] {
|
2017-06-13 21:02:11 +00:00
|
|
|
t.Errorf("expected service %s's port to be %d but found %d",
|
2019-11-18 18:04:01 +00:00
|
|
|
v.Name, ctx.Workload.DriverNetwork.PortMap["x"], v.Port)
|
2017-06-13 21:02:11 +00:00
|
|
|
}
|
2019-11-18 18:04:01 +00:00
|
|
|
case ctx.Workload.Services[2].Name: // y + host mode
|
2017-06-13 21:02:11 +00:00
|
|
|
if v.Port != yPort {
|
2017-06-26 19:53:43 +00:00
|
|
|
t.Errorf("expected service %s's port to be %d but found %d",
|
2017-06-13 21:02:11 +00:00
|
|
|
v.Name, yPort, v.Port)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
t.Errorf("unexpected service name: %q", v.Name)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-06-16 23:35:16 +00:00
|
|
|
|
|
|
|
// TestConsul_DriverNetwork_Change asserts that if a driver network is
|
|
|
|
// specified and a service updates its use its properly updated in Consul.
|
|
|
|
func TestConsul_DriverNetwork_Change(t *testing.T) {
|
2018-04-17 19:36:50 +00:00
|
|
|
t.Parallel()
|
|
|
|
ctx := setupFake(t)
|
2017-06-16 23:35:16 +00:00
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
ctx.Workload.Services = []*structs.Service{
|
2017-06-16 23:35:16 +00:00
|
|
|
{
|
|
|
|
Name: "service-foo",
|
|
|
|
PortLabel: "x",
|
|
|
|
AddressMode: structs.AddressModeAuto,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
ctx.Workload.DriverNetwork = &drivers.DriverNetwork{
|
2017-06-16 23:35:16 +00:00
|
|
|
PortMap: map[string]int{
|
|
|
|
"x": 8888,
|
|
|
|
"y": 9999,
|
|
|
|
},
|
|
|
|
IP: "172.18.0.2",
|
|
|
|
AutoAdvertise: false,
|
|
|
|
}
|
|
|
|
|
|
|
|
syncAndAssertPort := func(port int) {
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
if err := ctx.syncOnce(syncNewOps); err != nil {
|
2017-06-16 23:35:16 +00:00
|
|
|
t.Fatalf("unexpected error syncing task: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if n := len(ctx.FakeConsul.services); n != 1 {
|
|
|
|
t.Fatalf("expected 1 service but found: %d", n)
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, v := range ctx.FakeConsul.services {
|
|
|
|
switch v.Name {
|
2019-11-18 18:04:01 +00:00
|
|
|
case ctx.Workload.Services[0].Name:
|
2017-06-16 23:35:16 +00:00
|
|
|
if v.Port != port {
|
|
|
|
t.Errorf("expected service %s's port to be %d but found %d",
|
|
|
|
v.Name, port, v.Port)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
t.Errorf("unexpected service name: %q", v.Name)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initial service should advertise host port x
|
2019-11-18 18:04:01 +00:00
|
|
|
if err := ctx.ServiceClient.RegisterWorkload(ctx.Workload); err != nil {
|
2017-06-16 23:35:16 +00:00
|
|
|
t.Fatalf("unexpected error registering task: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
syncAndAssertPort(xPort)
|
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
// UpdateWorkload to use Host (shouldn't change anything)
|
|
|
|
origWorkload := ctx.Workload.Copy()
|
|
|
|
ctx.Workload.Services[0].AddressMode = structs.AddressModeHost
|
2017-06-16 23:35:16 +00:00
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
if err := ctx.ServiceClient.UpdateWorkload(origWorkload, ctx.Workload); err != nil {
|
2017-06-16 23:35:16 +00:00
|
|
|
t.Fatalf("unexpected error updating task: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
syncAndAssertPort(xPort)
|
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
// UpdateWorkload to use Driver (*should* change IP and port)
|
|
|
|
origWorkload = ctx.Workload.Copy()
|
|
|
|
ctx.Workload.Services[0].AddressMode = structs.AddressModeDriver
|
2017-06-16 23:35:16 +00:00
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
if err := ctx.ServiceClient.UpdateWorkload(origWorkload, ctx.Workload); err != nil {
|
2017-06-16 23:35:16 +00:00
|
|
|
t.Fatalf("unexpected error updating task: %v", err)
|
|
|
|
}
|
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
syncAndAssertPort(ctx.Workload.DriverNetwork.PortMap["x"])
|
2018-04-23 23:34:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// TestConsul_CanaryTags asserts CanaryTags are used when Canary=true
|
|
|
|
func TestConsul_CanaryTags(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
require := require.New(t)
|
|
|
|
ctx := setupFake(t)
|
|
|
|
|
|
|
|
canaryTags := []string{"tag1", "canary"}
|
2019-11-18 18:04:01 +00:00
|
|
|
ctx.Workload.Canary = true
|
|
|
|
ctx.Workload.Services[0].CanaryTags = canaryTags
|
2018-04-23 23:34:53 +00:00
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
require.NoError(ctx.ServiceClient.RegisterWorkload(ctx.Workload))
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
require.NoError(ctx.syncOnce(syncNewOps))
|
2018-04-23 23:34:53 +00:00
|
|
|
require.Len(ctx.FakeConsul.services, 1)
|
|
|
|
for _, service := range ctx.FakeConsul.services {
|
|
|
|
require.Equal(canaryTags, service.Tags)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Disable canary and assert tags are not the canary tags
|
2019-11-18 18:04:01 +00:00
|
|
|
origWorkload := ctx.Workload.Copy()
|
|
|
|
ctx.Workload.Canary = false
|
|
|
|
require.NoError(ctx.ServiceClient.UpdateWorkload(origWorkload, ctx.Workload))
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
require.NoError(ctx.syncOnce(syncNewOps))
|
2018-04-23 23:34:53 +00:00
|
|
|
require.Len(ctx.FakeConsul.services, 1)
|
|
|
|
for _, service := range ctx.FakeConsul.services {
|
|
|
|
require.NotEqual(canaryTags, service.Tags)
|
|
|
|
}
|
2018-04-24 00:03:31 +00:00
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
ctx.ServiceClient.RemoveWorkload(ctx.Workload)
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
require.NoError(ctx.syncOnce(syncNewOps))
|
2018-04-24 00:03:31 +00:00
|
|
|
require.Len(ctx.FakeConsul.services, 0)
|
2017-06-16 23:35:16 +00:00
|
|
|
}
|
2017-07-18 20:23:01 +00:00
|
|
|
|
2018-05-23 20:07:47 +00:00
|
|
|
// TestConsul_CanaryTags_NoTags asserts Tags are used when Canary=true and there
|
|
|
|
// are no specified canary tags
|
|
|
|
func TestConsul_CanaryTags_NoTags(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
require := require.New(t)
|
|
|
|
ctx := setupFake(t)
|
|
|
|
|
|
|
|
tags := []string{"tag1", "foo"}
|
2019-11-18 18:04:01 +00:00
|
|
|
ctx.Workload.Canary = true
|
|
|
|
ctx.Workload.Services[0].Tags = tags
|
2018-05-23 20:07:47 +00:00
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
require.NoError(ctx.ServiceClient.RegisterWorkload(ctx.Workload))
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
require.NoError(ctx.syncOnce(syncNewOps))
|
2018-05-23 20:07:47 +00:00
|
|
|
require.Len(ctx.FakeConsul.services, 1)
|
|
|
|
for _, service := range ctx.FakeConsul.services {
|
|
|
|
require.Equal(tags, service.Tags)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Disable canary and assert tags dont change
|
2019-11-18 18:04:01 +00:00
|
|
|
origWorkload := ctx.Workload.Copy()
|
|
|
|
ctx.Workload.Canary = false
|
|
|
|
require.NoError(ctx.ServiceClient.UpdateWorkload(origWorkload, ctx.Workload))
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
require.NoError(ctx.syncOnce(syncNewOps))
|
2018-05-23 20:07:47 +00:00
|
|
|
require.Len(ctx.FakeConsul.services, 1)
|
|
|
|
for _, service := range ctx.FakeConsul.services {
|
|
|
|
require.Equal(tags, service.Tags)
|
|
|
|
}
|
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
ctx.ServiceClient.RemoveWorkload(ctx.Workload)
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
require.NoError(ctx.syncOnce(syncNewOps))
|
2018-05-23 20:07:47 +00:00
|
|
|
require.Len(ctx.FakeConsul.services, 0)
|
|
|
|
}
|
|
|
|
|
2019-11-13 03:27:54 +00:00
|
|
|
// TestConsul_CanaryMeta asserts CanaryMeta are used when Canary=true
|
|
|
|
func TestConsul_CanaryMeta(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
require := require.New(t)
|
|
|
|
ctx := setupFake(t)
|
|
|
|
|
|
|
|
canaryMeta := map[string]string{"meta1": "canary"}
|
|
|
|
canaryMeta["external-source"] = "nomad"
|
2020-01-27 19:00:19 +00:00
|
|
|
ctx.Workload.Canary = true
|
|
|
|
ctx.Workload.Services[0].CanaryMeta = canaryMeta
|
2019-11-13 03:27:54 +00:00
|
|
|
|
2020-01-27 19:00:19 +00:00
|
|
|
require.NoError(ctx.ServiceClient.RegisterWorkload(ctx.Workload))
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
require.NoError(ctx.syncOnce(syncNewOps))
|
2019-11-13 03:27:54 +00:00
|
|
|
require.Len(ctx.FakeConsul.services, 1)
|
|
|
|
for _, service := range ctx.FakeConsul.services {
|
|
|
|
require.Equal(canaryMeta, service.Meta)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Disable canary and assert meta are not the canary meta
|
2020-01-27 19:00:19 +00:00
|
|
|
origWorkload := ctx.Workload.Copy()
|
|
|
|
ctx.Workload.Canary = false
|
|
|
|
require.NoError(ctx.ServiceClient.UpdateWorkload(origWorkload, ctx.Workload))
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
require.NoError(ctx.syncOnce(syncNewOps))
|
2019-11-13 03:27:54 +00:00
|
|
|
require.Len(ctx.FakeConsul.services, 1)
|
|
|
|
for _, service := range ctx.FakeConsul.services {
|
|
|
|
require.NotEqual(canaryMeta, service.Meta)
|
|
|
|
}
|
|
|
|
|
2020-01-27 19:00:19 +00:00
|
|
|
ctx.ServiceClient.RemoveWorkload(ctx.Workload)
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
require.NoError(ctx.syncOnce(syncNewOps))
|
2019-11-13 03:27:54 +00:00
|
|
|
require.Len(ctx.FakeConsul.services, 0)
|
|
|
|
}
|
|
|
|
|
|
|
|
// TestConsul_CanaryMeta_NoMeta asserts Meta are used when Canary=true and there
|
|
|
|
// are no specified canary meta
|
|
|
|
func TestConsul_CanaryMeta_NoMeta(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
require := require.New(t)
|
|
|
|
ctx := setupFake(t)
|
|
|
|
|
|
|
|
meta := map[string]string{"meta1": "foo"}
|
|
|
|
meta["external-source"] = "nomad"
|
2020-01-27 19:00:19 +00:00
|
|
|
ctx.Workload.Canary = true
|
|
|
|
ctx.Workload.Services[0].Meta = meta
|
2019-11-13 03:27:54 +00:00
|
|
|
|
2020-01-27 19:00:19 +00:00
|
|
|
require.NoError(ctx.ServiceClient.RegisterWorkload(ctx.Workload))
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
require.NoError(ctx.syncOnce(syncNewOps))
|
2019-11-13 03:27:54 +00:00
|
|
|
require.Len(ctx.FakeConsul.services, 1)
|
|
|
|
for _, service := range ctx.FakeConsul.services {
|
|
|
|
require.Equal(meta, service.Meta)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Disable canary and assert meta dont change
|
2020-01-27 19:00:19 +00:00
|
|
|
origWorkload := ctx.Workload.Copy()
|
|
|
|
ctx.Workload.Canary = false
|
|
|
|
require.NoError(ctx.ServiceClient.UpdateWorkload(origWorkload, ctx.Workload))
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
require.NoError(ctx.syncOnce(syncNewOps))
|
2019-11-13 03:27:54 +00:00
|
|
|
require.Len(ctx.FakeConsul.services, 1)
|
|
|
|
for _, service := range ctx.FakeConsul.services {
|
|
|
|
require.Equal(meta, service.Meta)
|
|
|
|
}
|
|
|
|
|
2020-01-27 19:00:19 +00:00
|
|
|
ctx.ServiceClient.RemoveWorkload(ctx.Workload)
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
require.NoError(ctx.syncOnce(syncNewOps))
|
2019-11-13 03:27:54 +00:00
|
|
|
require.Len(ctx.FakeConsul.services, 0)
|
|
|
|
}
|
|
|
|
|
2018-04-17 19:36:50 +00:00
|
|
|
// TestConsul_PeriodicSync asserts that Nomad periodically reconciles with
|
|
|
|
// Consul.
|
|
|
|
func TestConsul_PeriodicSync(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
ctx := setupFake(t)
|
|
|
|
defer ctx.ServiceClient.Shutdown()
|
|
|
|
|
|
|
|
// Lower periodic sync interval to speed up test
|
2020-03-29 21:34:20 +00:00
|
|
|
ctx.ServiceClient.periodicInterval = 1 * time.Millisecond
|
2018-04-17 19:36:50 +00:00
|
|
|
|
2020-03-29 21:34:20 +00:00
|
|
|
// Run for 20ms and assert hits >= 5 because each sync() calls multiple
|
2018-04-17 19:36:50 +00:00
|
|
|
// Consul APIs
|
|
|
|
go ctx.ServiceClient.Run()
|
|
|
|
|
|
|
|
select {
|
|
|
|
case <-ctx.ServiceClient.exitCh:
|
|
|
|
t.Fatalf("exited unexpectedly")
|
2020-03-29 21:34:20 +00:00
|
|
|
case <-time.After(20 * time.Millisecond):
|
2018-04-17 19:36:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
minHits := 5
|
|
|
|
if hits := ctx.FakeConsul.getHits(); hits < minHits {
|
|
|
|
t.Fatalf("expected at least %d hits but found %d", minHits, hits)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-18 20:23:01 +00:00
|
|
|
// TestIsNomadService asserts the isNomadService helper returns true for Nomad
|
|
|
|
// task IDs and false for unknown IDs and Nomad agent IDs (see #2827).
|
|
|
|
func TestIsNomadService(t *testing.T) {
|
2018-04-17 19:36:50 +00:00
|
|
|
t.Parallel()
|
|
|
|
|
2017-07-18 20:23:01 +00:00
|
|
|
tests := []struct {
|
|
|
|
id string
|
|
|
|
result bool
|
|
|
|
}{
|
|
|
|
{"_nomad-client-nomad-client-http", false},
|
|
|
|
{"_nomad-server-nomad-serf", false},
|
2017-12-08 01:08:25 +00:00
|
|
|
|
|
|
|
// Pre-0.7.1 style IDs still match
|
2017-07-18 20:23:01 +00:00
|
|
|
{"_nomad-executor-abc", true},
|
|
|
|
{"_nomad-executor", true},
|
2017-12-08 01:08:25 +00:00
|
|
|
|
|
|
|
// Post-0.7.1 style IDs match
|
|
|
|
{"_nomad-task-FBBK265QN4TMT25ND4EP42TJVMYJ3HR4", true},
|
|
|
|
|
2017-07-18 20:23:01 +00:00
|
|
|
{"not-nomad", false},
|
2017-12-08 01:08:25 +00:00
|
|
|
{"_nomad", false},
|
2017-07-18 20:23:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, test := range tests {
|
|
|
|
t.Run(test.id, func(t *testing.T) {
|
|
|
|
actual := isNomadService(test.id)
|
|
|
|
if actual != test.result {
|
2017-07-19 17:00:57 +00:00
|
|
|
t.Errorf("%q should be %t but found %t", test.id, test.result, actual)
|
2017-07-18 20:23:01 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2017-08-16 18:27:30 +00:00
|
|
|
|
2018-05-03 22:18:12 +00:00
|
|
|
// TestCreateCheckReg_HTTP asserts Nomad ServiceCheck structs are properly
|
|
|
|
// converted to Consul API AgentCheckRegistrations for HTTP checks.
|
|
|
|
func TestCreateCheckReg_HTTP(t *testing.T) {
|
|
|
|
t.Parallel()
|
2017-08-16 18:27:30 +00:00
|
|
|
check := &structs.ServiceCheck{
|
|
|
|
Name: "name",
|
|
|
|
Type: "http",
|
|
|
|
Path: "/path",
|
|
|
|
PortLabel: "label",
|
|
|
|
Method: "POST",
|
|
|
|
Header: map[string][]string{
|
|
|
|
"Foo": {"bar"},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
serviceID := "testService"
|
|
|
|
checkID := check.Hash(serviceID)
|
|
|
|
host := "localhost"
|
|
|
|
port := 41111
|
|
|
|
|
|
|
|
expected := &api.AgentCheckRegistration{
|
|
|
|
ID: checkID,
|
|
|
|
Name: "name",
|
|
|
|
ServiceID: serviceID,
|
2017-08-17 22:18:55 +00:00
|
|
|
AgentServiceCheck: api.AgentServiceCheck{
|
|
|
|
Timeout: "0s",
|
|
|
|
Interval: "0s",
|
|
|
|
HTTP: fmt.Sprintf("http://%s:%d/path", host, port),
|
|
|
|
Method: "POST",
|
|
|
|
Header: map[string][]string{
|
|
|
|
"Foo": {"bar"},
|
|
|
|
},
|
|
|
|
},
|
2017-08-16 18:27:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
actual, err := createCheckReg(serviceID, checkID, check, host, port)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("err: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if diff := pretty.Diff(actual, expected); len(diff) > 0 {
|
|
|
|
t.Fatalf("diff:\n%s\n", strings.Join(diff, "\n"))
|
|
|
|
}
|
|
|
|
}
|
2017-12-05 19:39:42 +00:00
|
|
|
|
2018-05-03 22:18:12 +00:00
|
|
|
// TestCreateCheckReg_GRPC asserts Nomad ServiceCheck structs are properly
|
|
|
|
// converted to Consul API AgentCheckRegistrations for GRPC checks.
|
|
|
|
func TestCreateCheckReg_GRPC(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
check := &structs.ServiceCheck{
|
|
|
|
Name: "name",
|
|
|
|
Type: "grpc",
|
|
|
|
PortLabel: "label",
|
|
|
|
GRPCService: "foo.Bar",
|
|
|
|
GRPCUseTLS: true,
|
|
|
|
TLSSkipVerify: true,
|
|
|
|
Timeout: time.Second,
|
|
|
|
Interval: time.Minute,
|
|
|
|
}
|
|
|
|
|
|
|
|
serviceID := "testService"
|
|
|
|
checkID := check.Hash(serviceID)
|
|
|
|
|
|
|
|
expected := &api.AgentCheckRegistration{
|
|
|
|
ID: checkID,
|
|
|
|
Name: "name",
|
|
|
|
ServiceID: serviceID,
|
|
|
|
AgentServiceCheck: api.AgentServiceCheck{
|
|
|
|
Timeout: "1s",
|
|
|
|
Interval: "1m0s",
|
|
|
|
GRPC: "localhost:8080/foo.Bar",
|
|
|
|
GRPCUseTLS: true,
|
|
|
|
TLSSkipVerify: true,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
actual, err := createCheckReg(serviceID, checkID, check, "localhost", 8080)
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, expected, actual)
|
|
|
|
}
|
|
|
|
|
2017-12-05 19:39:42 +00:00
|
|
|
// TestGetAddress asserts Nomad uses the correct ip and port for services and
|
|
|
|
// checks depending on port labels, driver networks, and address mode.
|
|
|
|
func TestGetAddress(t *testing.T) {
|
|
|
|
const HostIP = "127.0.0.1"
|
|
|
|
|
|
|
|
cases := []struct {
|
|
|
|
Name string
|
|
|
|
|
|
|
|
// Parameters
|
|
|
|
Mode string
|
|
|
|
PortLabel string
|
|
|
|
Host map[string]int // will be converted to structs.Networks
|
2019-01-04 23:01:35 +00:00
|
|
|
Driver *drivers.DriverNetwork
|
2020-10-15 19:32:21 +00:00
|
|
|
Ports structs.AllocatedPorts
|
|
|
|
Status *structs.AllocNetworkStatus
|
2017-12-05 19:39:42 +00:00
|
|
|
|
|
|
|
// Results
|
2017-12-20 23:02:34 +00:00
|
|
|
ExpectedIP string
|
|
|
|
ExpectedPort int
|
|
|
|
ExpectedErr string
|
2017-12-05 19:39:42 +00:00
|
|
|
}{
|
2018-01-12 23:32:51 +00:00
|
|
|
// Valid Configurations
|
2017-12-05 19:39:42 +00:00
|
|
|
{
|
|
|
|
Name: "ExampleService",
|
|
|
|
Mode: structs.AddressModeAuto,
|
|
|
|
PortLabel: "db",
|
|
|
|
Host: map[string]int{"db": 12435},
|
2019-01-04 23:01:35 +00:00
|
|
|
Driver: &drivers.DriverNetwork{
|
2017-12-05 19:39:42 +00:00
|
|
|
PortMap: map[string]int{"db": 6379},
|
|
|
|
IP: "10.1.2.3",
|
|
|
|
},
|
2017-12-20 23:02:34 +00:00
|
|
|
ExpectedIP: HostIP,
|
|
|
|
ExpectedPort: 12435,
|
2017-12-05 19:39:42 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "Host",
|
|
|
|
Mode: structs.AddressModeHost,
|
|
|
|
PortLabel: "db",
|
|
|
|
Host: map[string]int{"db": 12345},
|
2019-01-04 23:01:35 +00:00
|
|
|
Driver: &drivers.DriverNetwork{
|
2017-12-05 19:39:42 +00:00
|
|
|
PortMap: map[string]int{"db": 6379},
|
|
|
|
IP: "10.1.2.3",
|
|
|
|
},
|
2017-12-20 23:02:34 +00:00
|
|
|
ExpectedIP: HostIP,
|
|
|
|
ExpectedPort: 12345,
|
2017-12-05 19:39:42 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "Driver",
|
|
|
|
Mode: structs.AddressModeDriver,
|
|
|
|
PortLabel: "db",
|
|
|
|
Host: map[string]int{"db": 12345},
|
2019-01-04 23:01:35 +00:00
|
|
|
Driver: &drivers.DriverNetwork{
|
2017-12-05 19:39:42 +00:00
|
|
|
PortMap: map[string]int{"db": 6379},
|
|
|
|
IP: "10.1.2.3",
|
|
|
|
},
|
2017-12-20 23:02:34 +00:00
|
|
|
ExpectedIP: "10.1.2.3",
|
|
|
|
ExpectedPort: 6379,
|
2017-12-05 19:39:42 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "AutoDriver",
|
|
|
|
Mode: structs.AddressModeAuto,
|
|
|
|
PortLabel: "db",
|
|
|
|
Host: map[string]int{"db": 12345},
|
2019-01-04 23:01:35 +00:00
|
|
|
Driver: &drivers.DriverNetwork{
|
2017-12-05 19:39:42 +00:00
|
|
|
PortMap: map[string]int{"db": 6379},
|
|
|
|
IP: "10.1.2.3",
|
|
|
|
AutoAdvertise: true,
|
|
|
|
},
|
2017-12-20 23:02:34 +00:00
|
|
|
ExpectedIP: "10.1.2.3",
|
|
|
|
ExpectedPort: 6379,
|
2017-12-05 19:39:42 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "DriverCustomPort",
|
|
|
|
Mode: structs.AddressModeDriver,
|
|
|
|
PortLabel: "7890",
|
|
|
|
Host: map[string]int{"db": 12345},
|
2019-01-04 23:01:35 +00:00
|
|
|
Driver: &drivers.DriverNetwork{
|
2017-12-05 19:39:42 +00:00
|
|
|
PortMap: map[string]int{"db": 6379},
|
|
|
|
IP: "10.1.2.3",
|
|
|
|
},
|
2017-12-20 23:02:34 +00:00
|
|
|
ExpectedIP: "10.1.2.3",
|
|
|
|
ExpectedPort: 7890,
|
2017-12-05 19:39:42 +00:00
|
|
|
},
|
2018-01-12 23:32:51 +00:00
|
|
|
|
|
|
|
// Invalid Configurations
|
2017-12-05 19:39:42 +00:00
|
|
|
{
|
|
|
|
Name: "DriverWithoutNetwork",
|
|
|
|
Mode: structs.AddressModeDriver,
|
|
|
|
PortLabel: "db",
|
|
|
|
Host: map[string]int{"db": 12345},
|
|
|
|
Driver: nil,
|
2017-12-20 23:02:34 +00:00
|
|
|
ExpectedErr: "no driver network exists",
|
2017-12-05 19:39:42 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "DriverBadPort",
|
|
|
|
Mode: structs.AddressModeDriver,
|
|
|
|
PortLabel: "bad-port-label",
|
|
|
|
Host: map[string]int{"db": 12345},
|
2019-01-04 23:01:35 +00:00
|
|
|
Driver: &drivers.DriverNetwork{
|
2017-12-05 19:39:42 +00:00
|
|
|
PortMap: map[string]int{"db": 6379},
|
|
|
|
IP: "10.1.2.3",
|
|
|
|
},
|
2017-12-20 23:02:34 +00:00
|
|
|
ExpectedErr: "invalid port",
|
2017-12-05 19:39:42 +00:00
|
|
|
},
|
2017-12-08 06:04:22 +00:00
|
|
|
{
|
|
|
|
Name: "DriverZeroPort",
|
|
|
|
Mode: structs.AddressModeDriver,
|
|
|
|
PortLabel: "0",
|
2019-01-04 23:01:35 +00:00
|
|
|
Driver: &drivers.DriverNetwork{
|
2017-12-08 06:04:22 +00:00
|
|
|
IP: "10.1.2.3",
|
|
|
|
},
|
2017-12-20 23:02:34 +00:00
|
|
|
ExpectedErr: "invalid port",
|
2017-12-08 06:04:22 +00:00
|
|
|
},
|
2017-12-08 05:58:15 +00:00
|
|
|
{
|
|
|
|
Name: "HostBadPort",
|
|
|
|
Mode: structs.AddressModeHost,
|
|
|
|
PortLabel: "bad-port-label",
|
2017-12-20 23:02:34 +00:00
|
|
|
ExpectedErr: "invalid port",
|
2017-12-08 05:58:15 +00:00
|
|
|
},
|
2017-12-05 19:39:42 +00:00
|
|
|
{
|
|
|
|
Name: "InvalidMode",
|
|
|
|
Mode: "invalid-mode",
|
2017-12-19 00:18:42 +00:00
|
|
|
PortLabel: "80",
|
2017-12-20 23:02:34 +00:00
|
|
|
ExpectedErr: "invalid address mode",
|
2017-12-05 19:39:42 +00:00
|
|
|
},
|
2017-12-19 00:18:42 +00:00
|
|
|
{
|
2017-12-20 23:02:34 +00:00
|
|
|
Name: "NoPort_AutoMode",
|
2017-12-20 23:59:47 +00:00
|
|
|
Mode: structs.AddressModeAuto,
|
2017-12-20 23:02:34 +00:00
|
|
|
ExpectedIP: HostIP,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "NoPort_HostMode",
|
|
|
|
Mode: structs.AddressModeHost,
|
|
|
|
ExpectedIP: HostIP,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "NoPort_DriverMode",
|
|
|
|
Mode: structs.AddressModeDriver,
|
2019-01-04 23:01:35 +00:00
|
|
|
Driver: &drivers.DriverNetwork{
|
2017-12-20 23:02:34 +00:00
|
|
|
IP: "10.1.2.3",
|
|
|
|
},
|
|
|
|
ExpectedIP: "10.1.2.3",
|
2017-12-19 00:18:42 +00:00
|
|
|
},
|
2020-10-15 19:32:21 +00:00
|
|
|
|
|
|
|
// Scenarios using port 0.12 networking fields (NetworkStatus, AllocatedPortMapping)
|
|
|
|
{
|
|
|
|
Name: "ExampleServer_withAllocatedPorts",
|
|
|
|
Mode: structs.AddressModeAuto,
|
|
|
|
PortLabel: "db",
|
|
|
|
Ports: []structs.AllocatedPortMapping{
|
|
|
|
{
|
|
|
|
Label: "db",
|
|
|
|
Value: 12435,
|
|
|
|
To: 6379,
|
|
|
|
HostIP: HostIP,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Status: &structs.AllocNetworkStatus{
|
|
|
|
InterfaceName: "eth0",
|
|
|
|
Address: "172.26.0.1",
|
|
|
|
},
|
|
|
|
ExpectedIP: HostIP,
|
|
|
|
ExpectedPort: 12435,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "Host_withAllocatedPorts",
|
|
|
|
Mode: structs.AddressModeHost,
|
|
|
|
PortLabel: "db",
|
|
|
|
Ports: []structs.AllocatedPortMapping{
|
|
|
|
{
|
|
|
|
Label: "db",
|
|
|
|
Value: 12345,
|
|
|
|
To: 6379,
|
|
|
|
HostIP: HostIP,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Status: &structs.AllocNetworkStatus{
|
|
|
|
InterfaceName: "eth0",
|
|
|
|
Address: "172.26.0.1",
|
|
|
|
},
|
|
|
|
ExpectedIP: HostIP,
|
|
|
|
ExpectedPort: 12345,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "Driver_withAllocatedPorts",
|
|
|
|
Mode: structs.AddressModeDriver,
|
|
|
|
PortLabel: "db",
|
|
|
|
Ports: []structs.AllocatedPortMapping{
|
|
|
|
{
|
|
|
|
Label: "db",
|
|
|
|
Value: 12345,
|
|
|
|
To: 6379,
|
|
|
|
HostIP: HostIP,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Driver: &drivers.DriverNetwork{
|
|
|
|
IP: "10.1.2.3",
|
|
|
|
},
|
|
|
|
Status: &structs.AllocNetworkStatus{
|
|
|
|
InterfaceName: "eth0",
|
|
|
|
Address: "172.26.0.1",
|
|
|
|
},
|
|
|
|
ExpectedIP: "10.1.2.3",
|
|
|
|
ExpectedPort: 6379,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "AutoDriver_withAllocatedPorts",
|
|
|
|
Mode: structs.AddressModeAuto,
|
|
|
|
PortLabel: "db",
|
|
|
|
Ports: []structs.AllocatedPortMapping{
|
|
|
|
{
|
|
|
|
Label: "db",
|
|
|
|
Value: 12345,
|
|
|
|
To: 6379,
|
|
|
|
HostIP: HostIP,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Driver: &drivers.DriverNetwork{
|
|
|
|
IP: "10.1.2.3",
|
|
|
|
AutoAdvertise: true,
|
|
|
|
},
|
|
|
|
Status: &structs.AllocNetworkStatus{
|
|
|
|
InterfaceName: "eth0",
|
|
|
|
Address: "172.26.0.1",
|
|
|
|
},
|
|
|
|
ExpectedIP: "10.1.2.3",
|
|
|
|
ExpectedPort: 6379,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "DriverCustomPort_withAllocatedPorts",
|
|
|
|
Mode: structs.AddressModeDriver,
|
|
|
|
PortLabel: "7890",
|
|
|
|
Ports: []structs.AllocatedPortMapping{
|
|
|
|
{
|
|
|
|
Label: "db",
|
|
|
|
Value: 12345,
|
|
|
|
To: 6379,
|
|
|
|
HostIP: HostIP,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Driver: &drivers.DriverNetwork{
|
|
|
|
IP: "10.1.2.3",
|
|
|
|
},
|
|
|
|
Status: &structs.AllocNetworkStatus{
|
|
|
|
InterfaceName: "eth0",
|
|
|
|
Address: "172.26.0.1",
|
|
|
|
},
|
|
|
|
ExpectedIP: "10.1.2.3",
|
|
|
|
ExpectedPort: 7890,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "Host_MultiHostInterface",
|
|
|
|
Mode: structs.AddressModeAuto,
|
|
|
|
PortLabel: "db",
|
|
|
|
Ports: []structs.AllocatedPortMapping{
|
|
|
|
{
|
|
|
|
Label: "db",
|
|
|
|
Value: 12345,
|
|
|
|
To: 6379,
|
|
|
|
HostIP: "127.0.0.100",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Status: &structs.AllocNetworkStatus{
|
|
|
|
InterfaceName: "eth0",
|
|
|
|
Address: "172.26.0.1",
|
|
|
|
},
|
|
|
|
ExpectedIP: "127.0.0.100",
|
|
|
|
ExpectedPort: 12345,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "Alloc",
|
|
|
|
Mode: structs.AddressModeAlloc,
|
|
|
|
PortLabel: "db",
|
|
|
|
Ports: []structs.AllocatedPortMapping{
|
|
|
|
{
|
|
|
|
Label: "db",
|
|
|
|
Value: 12345,
|
|
|
|
To: 6379,
|
|
|
|
HostIP: HostIP,
|
|
|
|
},
|
2021-01-06 19:11:31 +00:00
|
|
|
},
|
|
|
|
Status: &structs.AllocNetworkStatus{
|
|
|
|
InterfaceName: "eth0",
|
|
|
|
Address: "172.26.0.1",
|
|
|
|
},
|
|
|
|
ExpectedIP: "172.26.0.1",
|
|
|
|
ExpectedPort: 6379,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "Alloc no to value",
|
|
|
|
Mode: structs.AddressModeAlloc,
|
|
|
|
PortLabel: "db",
|
|
|
|
Ports: []structs.AllocatedPortMapping{
|
|
|
|
{
|
|
|
|
Label: "db",
|
|
|
|
Value: 12345,
|
|
|
|
HostIP: HostIP,
|
|
|
|
},
|
2020-10-15 19:32:21 +00:00
|
|
|
},
|
|
|
|
Status: &structs.AllocNetworkStatus{
|
|
|
|
InterfaceName: "eth0",
|
|
|
|
Address: "172.26.0.1",
|
|
|
|
},
|
|
|
|
ExpectedIP: "172.26.0.1",
|
|
|
|
ExpectedPort: 12345,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "AllocCustomPort",
|
|
|
|
Mode: structs.AddressModeAlloc,
|
|
|
|
PortLabel: "6379",
|
|
|
|
Status: &structs.AllocNetworkStatus{
|
|
|
|
InterfaceName: "eth0",
|
|
|
|
Address: "172.26.0.1",
|
|
|
|
},
|
|
|
|
ExpectedIP: "172.26.0.1",
|
|
|
|
ExpectedPort: 6379,
|
|
|
|
},
|
2017-12-05 19:39:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, tc := range cases {
|
|
|
|
t.Run(tc.Name, func(t *testing.T) {
|
|
|
|
// convert host port map into a structs.Networks
|
|
|
|
networks := []*structs.NetworkResource{
|
|
|
|
{
|
|
|
|
IP: HostIP,
|
|
|
|
ReservedPorts: make([]structs.Port, len(tc.Host)),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
i := 0
|
|
|
|
for label, port := range tc.Host {
|
|
|
|
networks[0].ReservedPorts[i].Label = label
|
|
|
|
networks[0].ReservedPorts[i].Value = port
|
|
|
|
i++
|
|
|
|
}
|
|
|
|
|
|
|
|
// Run getAddress
|
2020-10-15 19:32:21 +00:00
|
|
|
ip, port, err := getAddress(tc.Mode, tc.PortLabel, networks, tc.Driver, tc.Ports, tc.Status)
|
2017-12-05 19:39:42 +00:00
|
|
|
|
|
|
|
// Assert the results
|
2017-12-20 23:02:34 +00:00
|
|
|
assert.Equal(t, tc.ExpectedIP, ip, "IP mismatch")
|
|
|
|
assert.Equal(t, tc.ExpectedPort, port, "Port mismatch")
|
|
|
|
if tc.ExpectedErr == "" {
|
2017-12-05 19:39:42 +00:00
|
|
|
assert.Nil(t, err)
|
|
|
|
} else {
|
2017-12-08 05:58:15 +00:00
|
|
|
if err == nil {
|
2017-12-20 23:02:34 +00:00
|
|
|
t.Fatalf("expected error containing %q but err=nil", tc.ExpectedErr)
|
2017-12-08 05:58:15 +00:00
|
|
|
} else {
|
2017-12-20 23:02:34 +00:00
|
|
|
assert.Contains(t, err.Error(), tc.ExpectedErr)
|
2017-12-08 05:58:15 +00:00
|
|
|
}
|
2017-12-05 19:39:42 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2019-06-13 12:57:27 +00:00
|
|
|
|
|
|
|
func TestConsul_ServiceName_Duplicates(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
ctx := setupFake(t)
|
|
|
|
require := require.New(t)
|
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
ctx.Workload.Services = []*structs.Service{
|
2019-06-13 12:57:27 +00:00
|
|
|
{
|
|
|
|
Name: "best-service",
|
|
|
|
PortLabel: "x",
|
|
|
|
Tags: []string{
|
|
|
|
"foo",
|
|
|
|
},
|
|
|
|
Checks: []*structs.ServiceCheck{
|
|
|
|
{
|
|
|
|
Name: "check-a",
|
|
|
|
Type: "tcp",
|
|
|
|
Interval: time.Second,
|
|
|
|
Timeout: time.Second,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "best-service",
|
|
|
|
PortLabel: "y",
|
|
|
|
Tags: []string{
|
|
|
|
"bar",
|
|
|
|
},
|
|
|
|
Checks: []*structs.ServiceCheck{
|
|
|
|
{
|
|
|
|
Name: "checky-mccheckface",
|
|
|
|
Type: "tcp",
|
|
|
|
Interval: time.Second,
|
|
|
|
Timeout: time.Second,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
Name: "worst-service",
|
|
|
|
PortLabel: "y",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
require.NoError(ctx.ServiceClient.RegisterWorkload(ctx.Workload))
|
2019-06-13 12:57:27 +00:00
|
|
|
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
require.NoError(ctx.syncOnce(syncNewOps))
|
2019-06-13 12:57:27 +00:00
|
|
|
|
|
|
|
require.Len(ctx.FakeConsul.services, 3)
|
|
|
|
|
|
|
|
for _, v := range ctx.FakeConsul.services {
|
2019-11-18 18:04:01 +00:00
|
|
|
if v.Name == ctx.Workload.Services[0].Name && v.Port == xPort {
|
|
|
|
require.ElementsMatch(v.Tags, ctx.Workload.Services[0].Tags)
|
2019-06-13 12:57:27 +00:00
|
|
|
require.Len(v.Checks, 1)
|
2019-11-18 18:04:01 +00:00
|
|
|
} else if v.Name == ctx.Workload.Services[1].Name && v.Port == yPort {
|
|
|
|
require.ElementsMatch(v.Tags, ctx.Workload.Services[1].Tags)
|
2019-06-13 12:57:27 +00:00
|
|
|
require.Len(v.Checks, 1)
|
2019-11-18 18:04:01 +00:00
|
|
|
} else if v.Name == ctx.Workload.Services[2].Name {
|
2019-06-13 12:57:27 +00:00
|
|
|
require.Len(v.Checks, 0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-06-14 14:57:46 +00:00
|
|
|
|
|
|
|
// TestConsul_ServiceDeregistration_OutOfProbation asserts that during in steady
|
|
|
|
// state we remove any services we don't reconize locally
|
|
|
|
func TestConsul_ServiceDeregistration_OutProbation(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
ctx := setupFake(t)
|
|
|
|
require := require.New(t)
|
|
|
|
|
|
|
|
ctx.ServiceClient.deregisterProbationExpiry = time.Now().Add(-1 * time.Hour)
|
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
remainingWorkload := testWorkload()
|
|
|
|
remainingWorkload.Services = []*structs.Service{
|
2019-06-14 14:57:46 +00:00
|
|
|
{
|
|
|
|
Name: "remaining-service",
|
|
|
|
PortLabel: "x",
|
|
|
|
Checks: []*structs.ServiceCheck{
|
|
|
|
{
|
|
|
|
Name: "check",
|
|
|
|
Type: "tcp",
|
|
|
|
Interval: time.Second,
|
|
|
|
Timeout: time.Second,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2019-11-18 18:04:01 +00:00
|
|
|
remainingWorkloadServiceID := MakeAllocServiceID(remainingWorkload.AllocID,
|
|
|
|
remainingWorkload.Name(), remainingWorkload.Services[0])
|
2019-06-14 14:57:46 +00:00
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
require.NoError(ctx.ServiceClient.RegisterWorkload(remainingWorkload))
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
require.NoError(ctx.syncOnce(syncNewOps))
|
2019-06-14 14:57:46 +00:00
|
|
|
require.Len(ctx.FakeConsul.services, 1)
|
|
|
|
require.Len(ctx.FakeConsul.checks, 1)
|
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
explicitlyRemovedWorkload := testWorkload()
|
|
|
|
explicitlyRemovedWorkload.Services = []*structs.Service{
|
2019-06-14 14:57:46 +00:00
|
|
|
{
|
|
|
|
Name: "explicitly-removed-service",
|
|
|
|
PortLabel: "y",
|
|
|
|
Checks: []*structs.ServiceCheck{
|
|
|
|
{
|
|
|
|
Name: "check",
|
|
|
|
Type: "tcp",
|
|
|
|
Interval: time.Second,
|
|
|
|
Timeout: time.Second,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2019-11-18 18:04:01 +00:00
|
|
|
explicitlyRemovedWorkloadServiceID := MakeAllocServiceID(explicitlyRemovedWorkload.AllocID,
|
|
|
|
explicitlyRemovedWorkload.Name(), explicitlyRemovedWorkload.Services[0])
|
2019-06-14 14:57:46 +00:00
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
require.NoError(ctx.ServiceClient.RegisterWorkload(explicitlyRemovedWorkload))
|
2019-06-14 14:57:46 +00:00
|
|
|
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
require.NoError(ctx.syncOnce(syncNewOps))
|
2019-06-14 14:57:46 +00:00
|
|
|
require.Len(ctx.FakeConsul.services, 2)
|
|
|
|
require.Len(ctx.FakeConsul.checks, 2)
|
|
|
|
|
|
|
|
// we register a task through nomad API then remove it out of band
|
2019-11-18 18:04:01 +00:00
|
|
|
outofbandWorkload := testWorkload()
|
|
|
|
outofbandWorkload.Services = []*structs.Service{
|
2019-06-14 14:57:46 +00:00
|
|
|
{
|
|
|
|
Name: "unknown-service",
|
|
|
|
PortLabel: "x",
|
|
|
|
Checks: []*structs.ServiceCheck{
|
|
|
|
{
|
|
|
|
Name: "check",
|
|
|
|
Type: "tcp",
|
|
|
|
Interval: time.Second,
|
|
|
|
Timeout: time.Second,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2019-11-18 18:04:01 +00:00
|
|
|
outofbandWorkloadServiceID := MakeAllocServiceID(outofbandWorkload.AllocID,
|
|
|
|
outofbandWorkload.Name(), outofbandWorkload.Services[0])
|
2019-06-14 14:57:46 +00:00
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
require.NoError(ctx.ServiceClient.RegisterWorkload(outofbandWorkload))
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
require.NoError(ctx.syncOnce(syncNewOps))
|
2019-06-14 14:57:46 +00:00
|
|
|
|
|
|
|
require.Len(ctx.FakeConsul.services, 3)
|
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
// remove outofbandWorkload from local services so it appears unknown to client
|
2019-06-14 14:57:46 +00:00
|
|
|
require.Len(ctx.ServiceClient.services, 3)
|
|
|
|
require.Len(ctx.ServiceClient.checks, 3)
|
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
delete(ctx.ServiceClient.services, outofbandWorkloadServiceID)
|
|
|
|
delete(ctx.ServiceClient.checks, MakeCheckID(outofbandWorkloadServiceID, outofbandWorkload.Services[0].Checks[0]))
|
2019-06-14 14:57:46 +00:00
|
|
|
|
|
|
|
require.Len(ctx.ServiceClient.services, 2)
|
|
|
|
require.Len(ctx.ServiceClient.checks, 2)
|
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
// Sync and ensure that explicitly removed service as well as outofbandWorkload were removed
|
2019-06-14 14:57:46 +00:00
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
ctx.ServiceClient.RemoveWorkload(explicitlyRemovedWorkload)
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
require.NoError(ctx.syncOnce(syncNewOps))
|
|
|
|
require.NoError(ctx.ServiceClient.sync(syncNewOps))
|
2019-06-14 14:57:46 +00:00
|
|
|
require.Len(ctx.FakeConsul.services, 1)
|
|
|
|
require.Len(ctx.FakeConsul.checks, 1)
|
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
require.Contains(ctx.FakeConsul.services, remainingWorkloadServiceID)
|
|
|
|
require.NotContains(ctx.FakeConsul.services, outofbandWorkloadServiceID)
|
|
|
|
require.NotContains(ctx.FakeConsul.services, explicitlyRemovedWorkloadServiceID)
|
2019-06-14 14:57:46 +00:00
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
require.Contains(ctx.FakeConsul.checks, MakeCheckID(remainingWorkloadServiceID, remainingWorkload.Services[0].Checks[0]))
|
|
|
|
require.NotContains(ctx.FakeConsul.checks, MakeCheckID(outofbandWorkloadServiceID, outofbandWorkload.Services[0].Checks[0]))
|
|
|
|
require.NotContains(ctx.FakeConsul.checks, MakeCheckID(explicitlyRemovedWorkloadServiceID, explicitlyRemovedWorkload.Services[0].Checks[0]))
|
2019-06-14 14:57:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// TestConsul_ServiceDeregistration_InProbation asserts that during initialization
|
|
|
|
// we only deregister services that were explicitly removed and leave unknown
|
|
|
|
// services untouched. This adds a grace period for restoring recovered tasks
|
|
|
|
// before deregistering them
|
|
|
|
func TestConsul_ServiceDeregistration_InProbation(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
ctx := setupFake(t)
|
|
|
|
require := require.New(t)
|
|
|
|
|
|
|
|
ctx.ServiceClient.deregisterProbationExpiry = time.Now().Add(1 * time.Hour)
|
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
remainingWorkload := testWorkload()
|
|
|
|
remainingWorkload.Services = []*structs.Service{
|
2019-06-14 14:57:46 +00:00
|
|
|
{
|
|
|
|
Name: "remaining-service",
|
|
|
|
PortLabel: "x",
|
|
|
|
Checks: []*structs.ServiceCheck{
|
|
|
|
{
|
|
|
|
Name: "check",
|
|
|
|
Type: "tcp",
|
|
|
|
Interval: time.Second,
|
|
|
|
Timeout: time.Second,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2019-11-18 18:04:01 +00:00
|
|
|
remainingWorkloadServiceID := MakeAllocServiceID(remainingWorkload.AllocID,
|
|
|
|
remainingWorkload.Name(), remainingWorkload.Services[0])
|
2019-06-14 14:57:46 +00:00
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
require.NoError(ctx.ServiceClient.RegisterWorkload(remainingWorkload))
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
require.NoError(ctx.syncOnce(syncNewOps))
|
2019-06-14 14:57:46 +00:00
|
|
|
require.Len(ctx.FakeConsul.services, 1)
|
|
|
|
require.Len(ctx.FakeConsul.checks, 1)
|
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
explicitlyRemovedWorkload := testWorkload()
|
|
|
|
explicitlyRemovedWorkload.Services = []*structs.Service{
|
2019-06-14 14:57:46 +00:00
|
|
|
{
|
|
|
|
Name: "explicitly-removed-service",
|
|
|
|
PortLabel: "y",
|
|
|
|
Checks: []*structs.ServiceCheck{
|
|
|
|
{
|
|
|
|
Name: "check",
|
|
|
|
Type: "tcp",
|
|
|
|
Interval: time.Second,
|
|
|
|
Timeout: time.Second,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2019-11-18 18:04:01 +00:00
|
|
|
explicitlyRemovedWorkloadServiceID := MakeAllocServiceID(explicitlyRemovedWorkload.AllocID,
|
|
|
|
explicitlyRemovedWorkload.Name(), explicitlyRemovedWorkload.Services[0])
|
2019-06-14 14:57:46 +00:00
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
require.NoError(ctx.ServiceClient.RegisterWorkload(explicitlyRemovedWorkload))
|
2019-06-14 14:57:46 +00:00
|
|
|
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
require.NoError(ctx.syncOnce(syncNewOps))
|
2019-06-14 14:57:46 +00:00
|
|
|
require.Len(ctx.FakeConsul.services, 2)
|
|
|
|
require.Len(ctx.FakeConsul.checks, 2)
|
|
|
|
|
|
|
|
// we register a task through nomad API then remove it out of band
|
2019-11-18 18:04:01 +00:00
|
|
|
outofbandWorkload := testWorkload()
|
|
|
|
outofbandWorkload.Services = []*structs.Service{
|
2019-06-14 14:57:46 +00:00
|
|
|
{
|
|
|
|
Name: "unknown-service",
|
|
|
|
PortLabel: "x",
|
|
|
|
Checks: []*structs.ServiceCheck{
|
|
|
|
{
|
|
|
|
Name: "check",
|
|
|
|
Type: "tcp",
|
|
|
|
Interval: time.Second,
|
|
|
|
Timeout: time.Second,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2019-11-18 18:04:01 +00:00
|
|
|
outofbandWorkloadServiceID := MakeAllocServiceID(outofbandWorkload.AllocID,
|
|
|
|
outofbandWorkload.Name(), outofbandWorkload.Services[0])
|
2019-06-14 14:57:46 +00:00
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
require.NoError(ctx.ServiceClient.RegisterWorkload(outofbandWorkload))
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
require.NoError(ctx.syncOnce(syncNewOps))
|
2019-06-14 14:57:46 +00:00
|
|
|
|
|
|
|
require.Len(ctx.FakeConsul.services, 3)
|
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
// remove outofbandWorkload from local services so it appears unknown to client
|
2019-06-14 14:57:46 +00:00
|
|
|
require.Len(ctx.ServiceClient.services, 3)
|
|
|
|
require.Len(ctx.ServiceClient.checks, 3)
|
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
delete(ctx.ServiceClient.services, outofbandWorkloadServiceID)
|
|
|
|
delete(ctx.ServiceClient.checks, MakeCheckID(outofbandWorkloadServiceID, outofbandWorkload.Services[0].Checks[0]))
|
2019-06-14 14:57:46 +00:00
|
|
|
|
|
|
|
require.Len(ctx.ServiceClient.services, 2)
|
|
|
|
require.Len(ctx.ServiceClient.checks, 2)
|
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
// Sync and ensure that explicitly removed service was removed, but outofbandWorkload remains
|
2019-06-14 14:57:46 +00:00
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
ctx.ServiceClient.RemoveWorkload(explicitlyRemovedWorkload)
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
require.NoError(ctx.syncOnce(syncNewOps))
|
|
|
|
require.NoError(ctx.ServiceClient.sync(syncNewOps))
|
2019-06-14 14:57:46 +00:00
|
|
|
require.Len(ctx.FakeConsul.services, 2)
|
|
|
|
require.Len(ctx.FakeConsul.checks, 2)
|
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
require.Contains(ctx.FakeConsul.services, remainingWorkloadServiceID)
|
|
|
|
require.Contains(ctx.FakeConsul.services, outofbandWorkloadServiceID)
|
|
|
|
require.NotContains(ctx.FakeConsul.services, explicitlyRemovedWorkloadServiceID)
|
2019-06-14 14:57:46 +00:00
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
require.Contains(ctx.FakeConsul.checks, MakeCheckID(remainingWorkloadServiceID, remainingWorkload.Services[0].Checks[0]))
|
|
|
|
require.Contains(ctx.FakeConsul.checks, MakeCheckID(outofbandWorkloadServiceID, outofbandWorkload.Services[0].Checks[0]))
|
|
|
|
require.NotContains(ctx.FakeConsul.checks, MakeCheckID(explicitlyRemovedWorkloadServiceID, explicitlyRemovedWorkload.Services[0].Checks[0]))
|
2019-06-14 14:57:46 +00:00
|
|
|
|
|
|
|
// after probation, outofband services and checks are removed
|
|
|
|
ctx.ServiceClient.deregisterProbationExpiry = time.Now().Add(-1 * time.Hour)
|
|
|
|
|
client: enable configuring enable_tag_override for services
Consul provides a feature of Service Definitions where the tags
associated with a service can be modified through the Catalog API,
overriding the value(s) configured in the agent's service configuration.
To enable this feature, the flag enable_tag_override must be configured
in the service definition.
Previously, Nomad did not allow configuring this flag, and thus the default
value of false was used. Now, it is configurable.
Because Nomad itself acts as a state machine around the the service definitions
of the tasks it manages, it's worth describing what happens when this feature
is enabled and why.
Consider the basic case where there is no Nomad, and your service is provided
to consul as a boring JSON file. The ultimate source of truth for the definition
of that service is the file, and is stored in the agent. Later, Consul performs
"anti-entropy" which synchronizes the Catalog (stored only the leaders). Then
with enable_tag_override=true, the tags field is available for "external"
modification through the Catalog API (rather than directly configuring the
service definition file, or using the Agent API). The important observation
is that if the service definition ever changes (i.e. the file is changed &
config reloaded OR the Agent API is used to modify the service), those
"external" tag values are thrown away, and the new service definition is
once again the source of truth.
In the Nomad case, Nomad itself is the source of truth over the Agent in
the same way the JSON file was the source of truth in the example above.
That means any time Nomad sets a new service definition, any externally
configured tags are going to be replaced. When does this happen? Only on
major lifecycle events, for example when a task is modified because of an
updated job spec from the 'nomad job run <existing>' command. Otherwise,
Nomad's periodic re-sync's with Consul will now no longer try to restore
the externally modified tag values (as long as enable_tag_override=true).
Fixes #2057
2020-02-07 21:22:19 +00:00
|
|
|
require.NoError(ctx.ServiceClient.sync(syncNewOps))
|
2019-06-14 14:57:46 +00:00
|
|
|
require.Len(ctx.FakeConsul.services, 1)
|
|
|
|
require.Len(ctx.FakeConsul.checks, 1)
|
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
require.Contains(ctx.FakeConsul.services, remainingWorkloadServiceID)
|
|
|
|
require.NotContains(ctx.FakeConsul.services, outofbandWorkloadServiceID)
|
|
|
|
require.NotContains(ctx.FakeConsul.services, explicitlyRemovedWorkloadServiceID)
|
2019-06-14 14:57:46 +00:00
|
|
|
|
2019-11-18 18:04:01 +00:00
|
|
|
require.Contains(ctx.FakeConsul.checks, MakeCheckID(remainingWorkloadServiceID, remainingWorkload.Services[0].Checks[0]))
|
|
|
|
require.NotContains(ctx.FakeConsul.checks, MakeCheckID(outofbandWorkloadServiceID, outofbandWorkload.Services[0].Checks[0]))
|
|
|
|
require.NotContains(ctx.FakeConsul.checks, MakeCheckID(explicitlyRemovedWorkloadServiceID, explicitlyRemovedWorkload.Services[0].Checks[0]))
|
2019-06-14 14:57:46 +00:00
|
|
|
|
|
|
|
}
|