1"""
2Return cached data from minions
3"""
4
5import fnmatch
6import logging
7import os
8
9import salt.cache
10import salt.config
11import salt.fileserver.gitfs
12import salt.log
13import salt.payload
14import salt.pillar.git_pillar
15import salt.runners.winrepo
16import salt.utils.args
17import salt.utils.gitfs
18import salt.utils.master
19from salt.exceptions import SaltInvocationError
20from salt.fileserver import clear_lock as _clear_lock
21
22log = logging.getLogger(__name__)
23
24__func_alias__ = {
25    "list_": "list",
26}
27
28
29def grains(tgt, tgt_type="glob", **kwargs):
30    """
31    .. versionchanged:: 2017.7.0
32        The ``expr_form`` argument has been renamed to ``tgt_type``, earlier
33        releases must use ``expr_form``.
34
35    Return cached grains of the targeted minions.
36
37    tgt
38        Target to match minion ids.
39
40        .. versionchanged:: 2017.7.5,2018.3.0
41            The ``tgt`` argument is now required to display cached grains. If
42            not used, the function will not return grains. This optional
43            argument will become mandatory in the Salt ``3001`` release.
44
45    tgt_type
46        The type of targeting to use for matching, such as ``glob``, ``list``,
47        etc.
48
49    CLI Example:
50
51    .. code-block:: bash
52
53        salt-run cache.grains '*'
54    """
55    pillar_util = salt.utils.master.MasterPillarUtil(
56        tgt, tgt_type, use_cached_grains=True, grains_fallback=False, opts=__opts__
57    )
58    cached_grains = pillar_util.get_minion_grains()
59    return cached_grains
60
61
62def pillar(tgt=None, tgt_type="glob", **kwargs):
63    """
64    .. versionchanged:: 2017.7.0
65        The ``expr_form`` argument has been renamed to ``tgt_type``, earlier
66        releases must use ``expr_form``.
67
68    Return cached pillars of the targeted minions if tgt is set.
69    If tgt is not set will return cached pillars for all minions.
70
71    CLI Example:
72
73    .. code-block:: bash
74
75        salt-run cache.pillar
76    """
77    pillar_util = salt.utils.master.MasterPillarUtil(
78        tgt,
79        tgt_type,
80        use_cached_grains=True,
81        grains_fallback=False,
82        use_cached_pillar=True,
83        pillar_fallback=False,
84        opts=__opts__,
85    )
86    cached_pillar = pillar_util.get_minion_pillar()
87    return cached_pillar
88
89
90def mine(tgt=None, tgt_type="glob", **kwargs):
91    """
92    .. versionchanged:: 2017.7.0
93        The ``expr_form`` argument has been renamed to ``tgt_type``, earlier
94        releases must use ``expr_form``.
95
96    Return cached mine data of the targeted minions
97
98    CLI Example:
99
100    .. code-block:: bash
101
102        salt-run cache.mine
103    """
104    pillar_util = salt.utils.master.MasterPillarUtil(
105        tgt,
106        tgt_type,
107        use_cached_grains=False,
108        grains_fallback=False,
109        use_cached_pillar=False,
110        pillar_fallback=False,
111        opts=__opts__,
112    )
113    cached_mine = pillar_util.get_cached_mine_data()
114    return cached_mine
115
116
117def _clear_cache(
118    tgt=None,
119    tgt_type="glob",
120    clear_pillar_flag=False,
121    clear_grains_flag=False,
122    clear_mine_flag=False,
123    clear_mine_func_flag=None,
124):
125    """
126    Clear the cached data/files for the targeted minions.
127    """
128    if tgt is None:
129        return False
130
131    pillar_util = salt.utils.master.MasterPillarUtil(
132        tgt,
133        tgt_type,
134        use_cached_grains=True,
135        grains_fallback=False,
136        use_cached_pillar=True,
137        pillar_fallback=False,
138        opts=__opts__,
139    )
140    return pillar_util.clear_cached_minion_data(
141        clear_pillar=clear_pillar_flag,
142        clear_grains=clear_grains_flag,
143        clear_mine=clear_mine_flag,
144        clear_mine_func=clear_mine_func_flag,
145    )
146
147
148def clear_pillar(tgt=None, tgt_type="glob"):
149    """
150    .. versionchanged:: 2017.7.0
151        The ``expr_form`` argument has been renamed to ``tgt_type``, earlier
152        releases must use ``expr_form``.
153
154    Clear the cached pillar data of the targeted minions
155
156    CLI Example:
157
158    .. code-block:: bash
159
160        salt-run cache.clear_pillar
161    """
162    return _clear_cache(tgt, tgt_type, clear_pillar_flag=True)
163
164
165def clear_grains(tgt=None, tgt_type="glob"):
166    """
167    .. versionchanged:: 2017.7.0
168        The ``expr_form`` argument has been renamed to ``tgt_type``, earlier
169        releases must use ``expr_form``.
170
171    Clear the cached grains data of the targeted minions
172
173    CLI Example:
174
175    .. code-block:: bash
176
177        salt-run cache.clear_grains
178    """
179    return _clear_cache(tgt, tgt_type, clear_grains_flag=True)
180
181
182def clear_mine(tgt=None, tgt_type="glob"):
183    """
184    .. versionchanged:: 2017.7.0
185        The ``expr_form`` argument has been renamed to ``tgt_type``, earlier
186        releases must use ``expr_form``.
187
188    Clear the cached mine data of the targeted minions
189
190    CLI Example:
191
192    .. code-block:: bash
193
194        salt-run cache.clear_mine
195    """
196    return _clear_cache(tgt, tgt_type, clear_mine_flag=True)
197
198
199def clear_mine_func(tgt=None, tgt_type="glob", clear_mine_func_flag=None):
200    """
201    .. versionchanged:: 2017.7.0
202        The ``expr_form`` argument has been renamed to ``tgt_type``, earlier
203        releases must use ``expr_form``.
204
205    Clear the cached mine function data of the targeted minions
206
207    CLI Example:
208
209    .. code-block:: bash
210
211        salt-run cache.clear_mine_func tgt='*' clear_mine_func_flag='network.interfaces'
212    """
213    return _clear_cache(tgt, tgt_type, clear_mine_func_flag=clear_mine_func_flag)
214
215
216def clear_all(tgt=None, tgt_type="glob"):
217    """
218    .. versionchanged:: 2017.7.0
219        The ``expr_form`` argument has been renamed to ``tgt_type``, earlier
220        releases must use ``expr_form``.
221
222    Clear the cached pillar, grains, and mine data of the targeted minions
223
224    CLI Example:
225
226    .. code-block:: bash
227
228        salt-run cache.clear_all
229    """
230    return _clear_cache(
231        tgt,
232        tgt_type,
233        clear_pillar_flag=True,
234        clear_grains_flag=True,
235        clear_mine_flag=True,
236    )
237
238
239def clear_git_lock(role, remote=None, **kwargs):
240    """
241    .. versionadded:: 2015.8.2
242
243    Remove the update locks for Salt components (gitfs, git_pillar, winrepo)
244    which use gitfs backend code from salt.utils.gitfs.
245
246    .. note::
247        Running :py:func:`cache.clear_all <salt.runners.cache.clear_all>` will
248        not include this function as it does for pillar, grains, and mine.
249
250        Additionally, executing this function with a ``role`` of ``gitfs`` is
251        equivalent to running ``salt-run fileserver.clear_lock backend=git``.
252
253    role
254        Which type of lock to remove (``gitfs``, ``git_pillar``, or
255        ``winrepo``)
256
257    remote
258        If specified, then any remotes which contain the passed string will
259        have their lock cleared. For example, a ``remote`` value of **github**
260        will remove the lock from all github.com remotes.
261
262    type : update,checkout,mountpoint
263        The types of lock to clear. Can be one or more of ``update``,
264        ``checkout``, and ``mountpoint``, and can be passed either as a
265        comma-separated or Python list.
266
267        .. versionadded:: 2015.8.8
268        .. versionchanged:: 2018.3.0
269            ``mountpoint`` lock type added
270
271    CLI Examples:
272
273    .. code-block:: bash
274
275        salt-run cache.clear_git_lock gitfs
276        salt-run cache.clear_git_lock git_pillar
277        salt-run cache.clear_git_lock git_pillar type=update
278        salt-run cache.clear_git_lock git_pillar type=update,checkout
279        salt-run cache.clear_git_lock git_pillar type='["update", "mountpoint"]'
280    """
281    kwargs = salt.utils.args.clean_kwargs(**kwargs)
282    type_ = salt.utils.args.split_input(
283        kwargs.pop("type", ["update", "checkout", "mountpoint"])
284    )
285    if kwargs:
286        salt.utils.args.invalid_kwargs(kwargs)
287
288    if role == "gitfs":
289        git_objects = [
290            salt.utils.gitfs.GitFS(
291                __opts__,
292                __opts__["gitfs_remotes"],
293                per_remote_overrides=salt.fileserver.gitfs.PER_REMOTE_OVERRIDES,
294                per_remote_only=salt.fileserver.gitfs.PER_REMOTE_ONLY,
295            )
296        ]
297    elif role == "git_pillar":
298        git_objects = []
299        for ext_pillar in __opts__["ext_pillar"]:
300            key = next(iter(ext_pillar))
301            if key == "git":
302                if not isinstance(ext_pillar["git"], list):
303                    continue
304                obj = salt.utils.gitfs.GitPillar(
305                    __opts__,
306                    ext_pillar["git"],
307                    per_remote_overrides=salt.pillar.git_pillar.PER_REMOTE_OVERRIDES,
308                    per_remote_only=salt.pillar.git_pillar.PER_REMOTE_ONLY,
309                    global_only=salt.pillar.git_pillar.GLOBAL_ONLY,
310                )
311                git_objects.append(obj)
312    elif role == "winrepo":
313        winrepo_dir = __opts__["winrepo_dir"]
314        winrepo_remotes = __opts__["winrepo_remotes"]
315
316        git_objects = []
317        for remotes, base_dir in (
318            (winrepo_remotes, winrepo_dir),
319            (__opts__["winrepo_remotes_ng"], __opts__["winrepo_dir_ng"]),
320        ):
321            obj = salt.utils.gitfs.WinRepo(
322                __opts__,
323                remotes,
324                per_remote_overrides=salt.runners.winrepo.PER_REMOTE_OVERRIDES,
325                per_remote_only=salt.runners.winrepo.PER_REMOTE_ONLY,
326                global_only=salt.runners.winrepo.GLOBAL_ONLY,
327                cache_root=base_dir,
328            )
329            git_objects.append(obj)
330    else:
331        raise SaltInvocationError("Invalid role '{}'".format(role))
332
333    ret = {}
334    for obj in git_objects:
335        for lock_type in type_:
336            cleared, errors = _clear_lock(
337                obj.clear_lock, role, remote=remote, lock_type=lock_type
338            )
339            if cleared:
340                ret.setdefault("cleared", []).extend(cleared)
341            if errors:
342                ret.setdefault("errors", []).extend(errors)
343    if not ret:
344        return "No locks were removed"
345    return ret
346
347
348def cloud(tgt, provider=None):
349    """
350    Return cloud cache data for target.
351
352    .. note:: Only works with glob matching
353
354    tgt
355      Glob Target to match minion ids
356
357    provider
358      Cloud Provider
359
360    CLI Example:
361
362    .. code-block:: bash
363
364        salt-run cache.cloud 'salt*'
365        salt-run cache.cloud glance.example.org provider=openstack
366    """
367    if not isinstance(tgt, str):
368        return {}
369
370    opts = salt.config.cloud_config(
371        os.path.join(os.path.dirname(__opts__["conf_file"]), "cloud")
372    )
373    if not opts.get("update_cachedir"):
374        return {}
375
376    cloud_cache = __utils__["cloud.list_cache_nodes_full"](opts=opts, provider=provider)
377    if cloud_cache is None:
378        return {}
379
380    ret = {}
381    for driver, providers in cloud_cache.items():
382        for provider, servers in providers.items():
383            for name, data in servers.items():
384                if fnmatch.fnmatch(name, tgt):
385                    ret[name] = data
386                    ret[name]["provider"] = provider
387    return ret
388
389
390def store(bank, key, data, cachedir=None):
391    """
392    Lists entries stored in the specified bank.
393
394    CLI Example:
395
396    .. code-block:: bash
397
398        salt-run cache.store mycache mykey 'The time has come the walrus said'
399    """
400    if cachedir is None:
401        cachedir = __opts__["cachedir"]
402
403    try:
404        cache = salt.cache.Cache(__opts__, cachedir=cachedir)
405    except TypeError:
406        cache = salt.cache.Cache(__opts__)
407    return cache.store(bank, key, data)
408
409
410def list_(bank, cachedir=None):
411    """
412    Lists entries stored in the specified bank.
413
414    CLI Example:
415
416    .. code-block:: bash
417
418        salt-run cache.list cloud/active/ec2/myec2 cachedir=/var/cache/salt/
419    """
420    if cachedir is None:
421        cachedir = __opts__["cachedir"]
422
423    try:
424        cache = salt.cache.Cache(__opts__, cachedir=cachedir)
425    except TypeError:
426        cache = salt.cache.Cache(__opts__)
427    return cache.list(bank)
428
429
430def fetch(bank, key, cachedir=None):
431    """
432    Fetch data from a salt.cache bank.
433
434    CLI Example:
435
436    .. code-block:: bash
437
438        salt-run cache.fetch cloud/active/ec2/myec2 myminion cachedir=/var/cache/salt/
439    """
440    if cachedir is None:
441        cachedir = __opts__["cachedir"]
442
443    try:
444        cache = salt.cache.Cache(__opts__, cachedir=cachedir)
445    except TypeError:
446        cache = salt.cache.Cache(__opts__)
447    return cache.fetch(bank, key)
448
449
450def flush(bank, key=None, cachedir=None):
451    """
452    Remove the key from the cache bank with all the key content. If no key is
453    specified remove the entire bank with all keys and sub-banks inside.
454
455    CLI Examples:
456
457    .. code-block:: bash
458
459        salt-run cache.flush cloud/active/ec2/myec2 cachedir=/var/cache/salt/
460        salt-run cache.flush cloud/active/ec2/myec2 myminion cachedir=/var/cache/salt/
461    """
462    if cachedir is None:
463        cachedir = __opts__["cachedir"]
464
465    try:
466        cache = salt.cache.Cache(__opts__, cachedir=cachedir)
467    except TypeError:
468        cache = salt.cache.Cache(__opts__)
469    return cache.flush(bank, key)
470