Skip to content

Commit 16b18b5

Browse files
committed
Use uuid4 instead of hostname
1 parent 72d1174 commit 16b18b5

File tree

2 files changed

+62
-19
lines changed

2 files changed

+62
-19
lines changed

awscli/telemetry.py

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@
1313
import hashlib
1414
import io
1515
import os
16-
import socket
1716
import sqlite3
1817
import sys
1918
import threading
2019
import time
20+
import uuid
2121
from dataclasses import dataclass
2222
from functools import cached_property
2323
from pathlib import Path
@@ -49,6 +49,17 @@ class CLISessionDatabaseConnection:
4949
timestamp INTEGER NOT NULL
5050
)
5151
"""
52+
_CREATE_HOST_ID_TABLE = """
53+
CREATE TABLE IF NOT EXISTS host_id (
54+
key INTEGER PRIMARY KEY,
55+
id TEXT UNIQUE NOT NULL
56+
)
57+
"""
58+
_INSERT_HOST_ID = """
59+
INSERT OR IGNORE INTO host_id (
60+
key, id
61+
) VALUES (?, ?)
62+
"""
5263
_ENABLE_WAL = 'PRAGMA journal_mode=WAL'
5364

5465
def __init__(self, connection=None):
@@ -69,12 +80,28 @@ def execute(self, query, *parameters):
6980
return sqlite3.Cursor(self._connection)
7081

7182
def _ensure_database_setup(self):
72-
self._create_record_table()
83+
self._create_session_table()
84+
self._create_host_id_table()
85+
self._ensure_host_id()
7386
self._try_to_enable_wal()
7487

75-
def _create_record_table(self):
88+
def _create_session_table(self):
7689
self.execute(self._CREATE_TABLE)
7790

91+
def _create_host_id_table(self):
92+
self.execute(self._CREATE_HOST_ID_TABLE)
93+
94+
def _ensure_host_id(self):
95+
self.execute(
96+
self._INSERT_HOST_ID,
97+
# Hardcode `0` as primary key to ensure
98+
# there's only ever 1 host id in the table.
99+
(
100+
0,
101+
str(uuid.uuid4()),
102+
),
103+
)
104+
78105
def _try_to_enable_wal(self):
79106
try:
80107
self.execute(self._ENABLE_WAL)
@@ -111,6 +138,11 @@ class CLISessionDatabaseReader:
111138
FROM session
112139
WHERE key = ?
113140
"""
141+
_READ_HOST_ID = """
142+
SELECT id
143+
FROM host_id
144+
WHERE key = 0
145+
"""
114146

115147
def __init__(self, connection):
116148
self._connection = connection
@@ -122,6 +154,10 @@ def read(self, key):
122154
return
123155
return CLISessionData(*result)
124156

157+
def read_host_id(self):
158+
cursor = self._connection.execute(self._READ_HOST_ID)
159+
return cursor.fetchone()[0]
160+
125161

126162
class CLISessionDatabaseSweeper:
127163
_DELETE_RECORDS = """
@@ -142,11 +178,11 @@ def sweep(self, timestamp):
142178

143179

144180
class CLISessionGenerator:
145-
def generate_session_id(self, hostname, tty, timestamp):
146-
return self._generate_md5_hash(hostname, tty, timestamp)
181+
def generate_session_id(self, host_id, tty, timestamp):
182+
return self._generate_md5_hash(host_id, tty, timestamp)
147183

148-
def generate_cache_key(self, hostname, tty):
149-
return self._generate_md5_hash(hostname, tty)
184+
def generate_cache_key(self, host_id, tty):
185+
return self._generate_md5_hash(host_id, tty)
150186

151187
def _generate_md5_hash(self, *args):
152188
str_to_hash = ""
@@ -167,12 +203,12 @@ def __init__(self, generator, writer, reader, sweeper):
167203

168204
@cached_property
169205
def cache_key(self):
170-
return self._generator.generate_cache_key(self._hostname, self._tty)
206+
return self._generator.generate_cache_key(self._host_id, self._tty)
171207

172208
@cached_property
173209
def _session_id(self):
174210
return self._generator.generate_session_id(
175-
self._hostname, self._tty, self._timestamp
211+
self._host_id, self._tty, self._timestamp
176212
)
177213

178214
@cached_property
@@ -206,12 +242,12 @@ def _tty(self):
206242
except (OSError, io.UnsupportedOperation):
207243
# Standard input was redirected to a pseudofile.
208244
# This can happen when running tests on IDEs or
209-
# running scripts with redirected input.
245+
# running scripts with redirected input, etc.
210246
return
211247

212248
@cached_property
213-
def _hostname(self):
214-
return socket.gethostname()
249+
def _host_id(self):
250+
return self._reader.read_host_id()
215251

216252
@cached_property
217253
def _timestamp(self):

tests/functional/test_telemetry.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,14 @@ def session_conn():
4747
) VALUES ('first_key', 'first_id', 5555555555)
4848
"""
4949
)
50+
# Overwrite host id with deterministic value for testing.
51+
conn.execute(
52+
"""
53+
INSERT OR REPLACE INTO host_id (
54+
key, id
55+
) VALUES (0, 'my-hostname')
56+
"""
57+
)
5058
return conn
5159

5260

@@ -93,11 +101,10 @@ def test_ensure_database_setup(self, session_conn):
93101
"""
94102
SELECT name
95103
FROM sqlite_master
96-
WHERE type='table'
97-
AND name='session';
104+
WHERE type='table';
98105
"""
99106
)
100-
assert cursor.fetchall() == [('session',)]
107+
assert cursor.fetchall() == [('session',), ('host_id',)]
101108

102109
def test_timeout_does_not_raise_exception(self, session_conn):
103110
class FakeConnection(sqlite3.Connection):
@@ -144,6 +151,10 @@ def test_read_nonexistent_record(self, session_reader):
144151
session_data = session_reader.read('bad_key')
145152
assert session_data is None
146153

154+
def test_read_host_id(self, session_reader):
155+
host_id = session_reader.read_host_id()
156+
assert host_id == 'my-hostname'
157+
147158

148159
class TestCLISessionDatabaseSweeper:
149160
def test_sweep(self, expired_data, session_reader, session_sweeper):
@@ -184,13 +195,11 @@ def test_generate_cache_key(self, session_generator):
184195
@skip_if_windows
185196
@patch('sys.stdin')
186197
@patch('time.time', return_value=5555555555)
187-
@patch('socket.gethostname', return_value='my-hostname')
188198
@patch('os.ttyname', return_value='my-tty')
189199
class TestCLISessionOrchestrator:
190200
def test_session_id_gets_cached(
191201
self,
192202
patched_tty_name,
193-
patched_hostname,
194203
patched_time,
195204
patched_stdin,
196205
session_sweeper,
@@ -212,7 +221,6 @@ def test_session_id_gets_cached(
212221
def test_cached_session_id_updated_if_expired(
213222
self,
214223
patched_tty_name,
215-
patched_hostname,
216224
patched_time,
217225
patched_stdin,
218226
session_sweeper,
@@ -249,7 +257,6 @@ def test_cached_session_id_updated_if_expired(
249257
def test_cached_session_id_not_updated_if_valid(
250258
self,
251259
patched_tty_name,
252-
patched_hostname,
253260
patched_time,
254261
patched_stdin,
255262
session_sweeper,

0 commit comments

Comments
 (0)