|
4 | 4 |
|
5 | 5 | import collections
|
6 | 6 | import copy
|
| 7 | +import datetime |
7 | 8 | import fnmatch
|
8 | 9 | import logging
|
9 |
| -import os |
10 | 10 | import sys
|
11 | 11 | import time
|
12 | 12 | import traceback
|
13 | 13 |
|
14 | 14 | import tornado.gen
|
15 | 15 |
|
| 16 | +import salt.cache |
16 | 17 | import salt.channel.client
|
17 | 18 | import salt.fileclient
|
18 | 19 | import salt.loader
|
19 | 20 | import salt.minion
|
20 | 21 | import salt.utils.args
|
21 |
| -import salt.utils.cache |
22 | 22 | import salt.utils.crypt
|
23 | 23 | import salt.utils.data
|
24 | 24 | import salt.utils.dictupdate
|
| 25 | +import salt.utils.master |
25 | 26 | import salt.utils.url
|
26 | 27 | from salt.exceptions import SaltClientError
|
27 | 28 | from salt.template import compile_template
|
@@ -393,144 +394,6 @@ def __del__(self):
|
393 | 394 | # pylint: enable=W1701
|
394 | 395 |
|
395 | 396 |
|
396 |
| -class PillarCache: |
397 |
| - """ |
398 |
| - Return a cached pillar if it exists, otherwise cache it. |
399 |
| -
|
400 |
| - Pillar caches are structed in two diminensions: minion_id with a dict of |
401 |
| - saltenvs. Each saltenv contains a pillar dict |
402 |
| -
|
403 |
| - Example data structure: |
404 |
| -
|
405 |
| - ``` |
406 |
| - {'minion_1': |
407 |
| - {'base': {'pilar_key_1' 'pillar_val_1'} |
408 |
| - } |
409 |
| - """ |
410 |
| - |
411 |
| - # TODO ABC? |
412 |
| - def __init__( |
413 |
| - self, |
414 |
| - opts, |
415 |
| - grains, |
416 |
| - minion_id, |
417 |
| - saltenv, |
418 |
| - ext=None, |
419 |
| - functions=None, |
420 |
| - pillar_override=None, |
421 |
| - pillarenv=None, |
422 |
| - extra_minion_data=None, |
423 |
| - clean_cache=False, |
424 |
| - ): |
425 |
| - # Yes, we need all of these because we need to route to the Pillar object |
426 |
| - # if we have no cache. This is another refactor target. |
427 |
| - |
428 |
| - # Go ahead and assign these because they may be needed later |
429 |
| - self.opts = opts |
430 |
| - self.grains = grains |
431 |
| - self.minion_id = minion_id |
432 |
| - self.ext = ext |
433 |
| - self.functions = functions |
434 |
| - self.pillar_override = pillar_override |
435 |
| - self.pillarenv = pillarenv |
436 |
| - self.clean_cache = clean_cache |
437 |
| - self.extra_minion_data = extra_minion_data |
438 |
| - |
439 |
| - if saltenv is None: |
440 |
| - self.saltenv = "base" |
441 |
| - else: |
442 |
| - self.saltenv = saltenv |
443 |
| - |
444 |
| - # Determine caching backend |
445 |
| - self.cache = salt.utils.cache.CacheFactory.factory( |
446 |
| - self.opts["pillar_cache_backend"], |
447 |
| - self.opts["pillar_cache_ttl"], |
448 |
| - minion_cache_path=self._minion_cache_path(minion_id), |
449 |
| - ) |
450 |
| - |
451 |
| - def _minion_cache_path(self, minion_id): |
452 |
| - """ |
453 |
| - Return the path to the cache file for the minion. |
454 |
| -
|
455 |
| - Used only for disk-based backends |
456 |
| - """ |
457 |
| - return os.path.join(self.opts["cachedir"], "pillar_cache", minion_id) |
458 |
| - |
459 |
| - def fetch_pillar(self): |
460 |
| - """ |
461 |
| - In the event of a cache miss, we need to incur the overhead of caching |
462 |
| - a new pillar. |
463 |
| - """ |
464 |
| - log.debug("Pillar cache getting external pillar with ext: %s", self.ext) |
465 |
| - fresh_pillar = Pillar( |
466 |
| - self.opts, |
467 |
| - self.grains, |
468 |
| - self.minion_id, |
469 |
| - self.saltenv, |
470 |
| - ext=self.ext, |
471 |
| - functions=self.functions, |
472 |
| - pillar_override=None, |
473 |
| - pillarenv=self.pillarenv, |
474 |
| - extra_minion_data=self.extra_minion_data, |
475 |
| - ) |
476 |
| - return fresh_pillar.compile_pillar() |
477 |
| - |
478 |
| - def clear_pillar(self): |
479 |
| - """ |
480 |
| - Clear the cache |
481 |
| - """ |
482 |
| - self.cache.clear() |
483 |
| - |
484 |
| - return True |
485 |
| - |
486 |
| - def compile_pillar(self, *args, **kwargs): # Will likely just be pillar_dirs |
487 |
| - if self.clean_cache: |
488 |
| - self.clear_pillar() |
489 |
| - log.debug( |
490 |
| - "Scanning pillar cache for information about minion %s and pillarenv %s", |
491 |
| - self.minion_id, |
492 |
| - self.pillarenv, |
493 |
| - ) |
494 |
| - if self.opts["pillar_cache_backend"] == "memory": |
495 |
| - cache_dict = self.cache |
496 |
| - else: |
497 |
| - cache_dict = self.cache._dict |
498 |
| - |
499 |
| - log.debug("Scanning cache: %s", cache_dict) |
500 |
| - # Check the cache! |
501 |
| - if self.minion_id in self.cache: # Keyed by minion_id |
502 |
| - # TODO Compare grains, etc? |
503 |
| - if self.pillarenv in self.cache[self.minion_id]: |
504 |
| - # We have a cache hit! Send it back. |
505 |
| - log.debug( |
506 |
| - "Pillar cache hit for minion %s and pillarenv %s", |
507 |
| - self.minion_id, |
508 |
| - self.pillarenv, |
509 |
| - ) |
510 |
| - return self.cache[self.minion_id][self.pillarenv] |
511 |
| - else: |
512 |
| - # We found the minion but not the env. Store it. |
513 |
| - fresh_pillar = self.fetch_pillar() |
514 |
| - |
515 |
| - minion_cache = self.cache[self.minion_id] |
516 |
| - minion_cache[self.pillarenv] = fresh_pillar |
517 |
| - self.cache[self.minion_id] = minion_cache |
518 |
| - |
519 |
| - log.debug( |
520 |
| - "Pillar cache miss for pillarenv %s for minion %s", |
521 |
| - self.pillarenv, |
522 |
| - self.minion_id, |
523 |
| - ) |
524 |
| - return fresh_pillar |
525 |
| - else: |
526 |
| - # We haven't seen this minion yet in the cache. Store it. |
527 |
| - fresh_pillar = self.fetch_pillar() |
528 |
| - self.cache[self.minion_id] = {self.pillarenv: fresh_pillar} |
529 |
| - log.debug("Pillar cache miss for minion %s", self.minion_id) |
530 |
| - log.debug("Current pillar cache: %s", cache_dict) # FIXME hack! |
531 |
| - return fresh_pillar |
532 |
| - |
533 |
| - |
534 | 397 | class Pillar:
|
535 | 398 | """
|
536 | 399 | Read over the pillar top files and render the pillar data
|
@@ -1391,3 +1254,96 @@ class AsyncPillar(Pillar):
|
1391 | 1254 | def compile_pillar(self, ext=True):
|
1392 | 1255 | ret = super().compile_pillar(ext=ext)
|
1393 | 1256 | raise tornado.gen.Return(ret)
|
| 1257 | + |
| 1258 | + |
| 1259 | +class PillarCache(Pillar): |
| 1260 | + """ |
| 1261 | + Return a cached pillar if it exists, otherwise cache it. |
| 1262 | +
|
| 1263 | + Pillar caches are structed in two diminensions: minion_id with a dict of |
| 1264 | + saltenvs. Each saltenv contains a pillar dict |
| 1265 | +
|
| 1266 | + Example data structure: |
| 1267 | +
|
| 1268 | + ``` |
| 1269 | + {'minion_1': |
| 1270 | + {'base': {'pilar_key_1' 'pillar_val_1'} |
| 1271 | + } |
| 1272 | + """ |
| 1273 | + |
| 1274 | + def __init__( |
| 1275 | + self, |
| 1276 | + *args, |
| 1277 | + clean_cache=False, |
| 1278 | + pillar_override=None, |
| 1279 | + **kwargs, |
| 1280 | + ): |
| 1281 | + super().__init__(*args, **kwargs) |
| 1282 | + self.clean_cache = clean_cache |
| 1283 | + self.pillar_override = pillar_override |
| 1284 | + self.cache = salt.cache.factory( |
| 1285 | + self.opts, |
| 1286 | + driver=self.opts["pillar.cache_driver"], |
| 1287 | + expires=self.opts["pillar_cache_ttl"], |
| 1288 | + ) |
| 1289 | + |
| 1290 | + @property |
| 1291 | + def pillar_key(self): |
| 1292 | + if not self.opts["pillarenv"]: |
| 1293 | + return self.minion_id |
| 1294 | + else: |
| 1295 | + return f"{self.minion_id}.{self.opts['pillarenv']}" |
| 1296 | + |
| 1297 | + def cached_pillar(self): |
| 1298 | + """ |
| 1299 | + Return the cached pillar if it exists, or None |
| 1300 | + """ |
| 1301 | + return self.cache.fetch("pillar", self.pillar_key) |
| 1302 | + |
| 1303 | + def clear_pillar(self): |
| 1304 | + """ |
| 1305 | + Clea the pillar cache, if it exists |
| 1306 | + """ |
| 1307 | + return self.cache.flush("pillar", self.pillar_key) |
| 1308 | + |
| 1309 | + def compile_pillar(self, *args, **kwargs): # Will likely just be pillar_dirs |
| 1310 | + # matching to consume the same dataset |
| 1311 | + if self.clean_cache: |
| 1312 | + self.clear_pillar() |
| 1313 | + log.debug( |
| 1314 | + "Scanning pillar cache for information about minion %s and pillarenv %s", |
| 1315 | + self.minion_id, |
| 1316 | + self.opts["pillarenv"], |
| 1317 | + ) |
| 1318 | + |
| 1319 | + # Check the cache! |
| 1320 | + pillar_data = self.cached_pillar() |
| 1321 | + if pillar_data: |
| 1322 | + log.debug( |
| 1323 | + "Pillar cache hit for minion %s and pillarenv %s", |
| 1324 | + self.minion_id, |
| 1325 | + self.opts["pillarenv"], |
| 1326 | + ) |
| 1327 | + else: |
| 1328 | + # We found the minion but not the env. Store it. |
| 1329 | + log.debug( |
| 1330 | + "Pillar cache miss for pillarenv %s for minion %s", |
| 1331 | + self.opts["pillarenv"], |
| 1332 | + self.minion_id, |
| 1333 | + ) |
| 1334 | + pillar_data = super().compile_pillar(*args, **kwargs) |
| 1335 | + |
| 1336 | + self.cache.store("pillar", self.pillar_key, pillar_data) |
| 1337 | + |
| 1338 | + # we dont want the pillar_override baked into the cached compile_pillar from above |
| 1339 | + if self.pillar_override: |
| 1340 | + pillar_data = merge( |
| 1341 | + pillar_data, |
| 1342 | + self.pillar_override, |
| 1343 | + self.opts.get("pillar_source_merging_strategy", "smart"), |
| 1344 | + self.opts.get("renderer", "yaml"), |
| 1345 | + self.opts.get("pillar_merge_lists", False), |
| 1346 | + ) |
| 1347 | + pillar_data.update(self.pillar_override) |
| 1348 | + |
| 1349 | + return pillar_data |
0 commit comments