diff --git a/modules.go b/modules.go index 11726f7..f4bfcad 100644 --- a/modules.go +++ b/modules.go @@ -2413,6 +2413,11 @@ func (e *Executor) moduleHostname(ctx context.Context, client sshExecutorClient, return nil, coreerr.E("Executor.moduleHostname", "name required", nil) } + currentStdout, _, currentRC, currentErr := client.Run(ctx, "hostname") + if currentErr == nil && currentRC == 0 && corexTrimSpace(currentStdout) == name { + return &TaskResult{Changed: false, Msg: "hostname already set"}, nil + } + // Set hostname cmd := sprintf("hostnamectl set-hostname %q || hostname %q", name, name) stdout, stderr, rc, err := client.Run(ctx, cmd) diff --git a/modules_adv_test.go b/modules_adv_test.go index 75bb1a0..1fea36a 100644 --- a/modules_adv_test.go +++ b/modules_adv_test.go @@ -140,6 +140,41 @@ func TestModulesAdv_ModuleUser_Good_CommandFailure(t *testing.T) { assert.Contains(t, result.Msg, "Permission denied") } +// --- hostname module --- + +func TestModulesAdv_ModuleHostname_Good_IdempotentWhenAlreadySet(t *testing.T) { + e, mock := newTestExecutorWithMock("host1") + mock.expectCommand(`^hostname$`, "web01\n", "", 0) + + result, err := e.moduleHostname(context.Background(), mock, map[string]any{ + "name": "web01", + }) + + require.NoError(t, err) + assert.False(t, result.Changed) + assert.Equal(t, "hostname already set", result.Msg) + assert.True(t, mock.hasExecuted(`^hostname$`)) + assert.False(t, mock.hasExecuted(`hostnamectl set-hostname`)) +} + +func TestModulesAdv_ModuleHostname_Good_ChangesWhenDifferent(t *testing.T) { + e, mock := newTestExecutorWithMock("host1") + mock.expectCommand(`^hostname$`, "old-host\n", "", 0) + mock.expectCommand(`hostnamectl set-hostname "new-host" \|\| hostname "new-host"`, "", "", 0) + mock.expectCommand(`sed -i 's/127\.0\.1\.1\..*/127.0.1.1\tnew-host/' /etc/hosts`, "", "", 0) + + result, err := e.moduleHostname(context.Background(), mock, map[string]any{ + "name": "new-host", + }) + + require.NoError(t, err) + assert.True(t, result.Changed) + assert.False(t, result.Failed) + assert.True(t, mock.hasExecuted(`^hostname$`)) + assert.True(t, mock.hasExecuted(`hostnamectl set-hostname`)) + assert.True(t, mock.hasExecuted(`sed -i`)) +} + // --- group module --- func TestModulesAdv_ModuleGroup_Good_CreateNewGroup(t *testing.T) {