Move kubequery dependency to monorepo (#16027)

#15561

We didn't find a way to preserve history of the original fork (see
[here](https://github.com/fleetdm/fleet/issues/15561#issuecomment-1883473504),
thus we are moving it with one commit.

The second commit updates a reference.
This commit is contained in:
Lucas Manuel Rodriguez 2024-01-11 08:30:26 -03:00 committed by GitHub
parent 78ad2ed558
commit 3b2e97db89
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
154 changed files with 25768 additions and 1 deletions

View File

@ -0,0 +1,18 @@
# Copyright (c) 2020-present, The kubequery authors
#
# This source code is licensed as defined by the LICENSE file found in the
# root directory of this source tree.
#
# SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
version: 2
cli:
server: https://app.fossa.com
fetcher: custom
project: git@github.com:Uptycs/kubequery.git
analyze:
modules:
- name: github.com/Uptycs/kubequery/cmd/kubequery
type: go
target: github.com/Uptycs/kubequery/cmd/kubequery
path: cmd/kubequery

14
infrastructure/kubequery/.gitignore vendored Normal file
View File

@ -0,0 +1,14 @@
# Copyright (c) 2020-present, The kubequery authors
#
# This source code is licensed as defined by the LICENSE file found in the
# root directory of this source tree.
#
# SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
.vscode
vendor
kubequery.yaml
/bin/genschema
/bin/gentables
/bin/kubequery
/bin/uuidgen

View File

@ -0,0 +1,158 @@
# kubequery change log
<a name="1.1.1"></a>
## [1.1.1](https://github.com/Uptycs/kubequery/releases/tag/1.1.1)
[Git Commits](https://github.com/Uptycs/kubequery/compare/1.1.0...1.1.1)
### New Features
### Under the Hood improvements
* Upgrade to basequery 5.0.2
* Upgraded to Go 1.17
### Table Changes
### Bug Fixes
### Documentation
### Build
### Security Issues
### Packs
<a name="1.1.0"></a>
## [1.1.0](https://github.com/Uptycs/kubequery/releases/tag/1.1.0)
[Git Commits](https://github.com/Uptycs/kubequery/compare/1.0.0...1.1.0)
### New Features
* Helm chart to install kubequery
* Support for Kubernetes 1.22
### Under the Hood improvements
* Upgrade to basequery 4.9.0
* Upgraded to client go version 0.22
### Table Changes
* k8s 1.22 caused few table [schemas changes](https://github.com/Uptycs/kubequery/commit/a70e9a42f6f85ca1a0ebd23575590c73562fab83#diff-79f5d80ee02a931b2bf12fd018b6edeb447abd58e1fb85ae155ae932ec29ad9d):
* kubernetes_stateful_sets
* kubernetes_jobs
* kubernetes_persistent_volume_claims
* kubernetes_services
### Bug Fixes
* Check container status before iterating over contents. [Issue 16](https://github.com/Uptycs/kubequery/issues/16)
### Documentation
* Added helm related details in README.md
### Build
### Security Issues
### Packs
<a name="1.0.0"></a>
## [1.0.0](https://github.com/Uptycs/kubequery/releases/tag/1.0.0)
[Git Commits](https://github.com/Uptycs/kubequery/compare/0.3.0...1.0.0)
### New Features
* New `kubequeryi` command line to easily invoke shell
* Easy to use with [query-tls](https://github.com/Uptycs/query-tls)
### Under the Hood improvements
* Upgrade to basequery 4.8.0
* Switch to light weight busybox docker image
* Simple NodeJS based integration test
### Table Changes
* Added `cluster_name` and `cluster_uid` to tables missing those columns
* Break up `resources` in `*_containers` tables to `resource_limits` and `resource_requests`
* Added new table `kubernetes_component_statuses`
* Removed table `kubernetes_storage_capacities`
### Bug Fixes
### Documentation
### Build
* Upgrade to Go 1.16
### Security Issues
### Packs
* Added default query pack for all kubernetes tables
<a name="0.3.0"></a>
## [0.3.0](https://github.com/Uptycs/kubequery/releases/tag/0.3.0)
[Git Commits](https://github.com/Uptycs/kubequery/compare/0.2.0...0.3.0)
### New Features
### Under the Hood improvements
* Upgrade to basequery 4.7.0
### Table Changes
### Bug Fixes
### Documentation
* Validate the installation was successful [PR-12](https://github.com/Uptycs/kubequery/pull/12)
### Build
### Security Issues
### Packs
<a name="0.2.0"></a>
## [0.2.0](https://github.com/Uptycs/kubequery/releases/tag/0.2.0)
[Git Commits](https://github.com/Uptycs/kubequery/compare/0.1.0...0.2.0)
### New Features
* Added `kubernetes_events` table.
### Under the Hood improvements
* Switch to [basequery](https://github.com/Uptycs/basequery). This is stripped download version of Osquery with support for extension events and other features.
### Table Changes
* kubernetes_events
### Bug Fixes
### Documentation
* Validate the installation was successful [PR-12](https://github.com/Uptycs/kubequery/pull/12)
### Build
### Security Issues
### Packs

View File

@ -0,0 +1,133 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
[kubequery@uptycs.com](mailto:kubequery@uptycs.com).
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
[https://www.contributor-covenant.org/version/2/0/code_of_conduct.html][v2.0].
Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
For answers to common questions about this code of conduct, see the FAQ at
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available
at [https://www.contributor-covenant.org/translations][translations].
[homepage]: https://www.contributor-covenant.org
[v2.0]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html
[Mozilla CoC]: https://github.com/mozilla/diversity
[FAQ]: https://www.contributor-covenant.org/faq
[translations]: https://www.contributor-covenant.org/translations

View File

@ -0,0 +1,51 @@
# Contributing to kubequery
Welcome and thank you for considering contributing to kubequery open source.
Reading and following these guidelines will help us make the contribution process easy and effective for everyone involved. It also communicates that you agree to respect the time of the developers managing and developing these open source projects. In return, we will reciprocate that respect by addressing your issue, assessing changes, and helping you finalize your pull requests.
## Quicklinks
* [Code of Conduct](#code-of-conduct)
* [Getting Started](#getting-started)
* [Issues](#issues)
* [Pull Requests](#pull-requests)
## Code of Conduct
By participating and contributing to this project, you agree to uphold our [Code of Conduct](https://github.com/Uptycs/kubequery/blob/master/CODE_OF_CONDUCT.md).
## Getting Started
Contributions are made to this repo via Issues and Pull Requests (PRs). A few general guidelines that cover both:
- To report security vulnerabilities, please email [kubequery@uptycs.com](mailto:kubequery@uptycs.com).
- Search for existing Issues and PRs before creating your own.
### Issues
Issues should be used to report problems with kubequery, request a new feature, or to discuss potential changes before a PR is created. When you create a new issue, a template will be loaded that will guide you through collecting and providing the information we need to investigate.
If you find an issue that addresses the problem you're having, please add your own reproduction information to the existing issue rather than creating a new one. Adding a [reaction](https://github.blog/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/) can also help be indicating to our maintainers that a particular problem is affecting more than just the reporter.
### Pull Requests
PRs to our libraries are always welcome and can be a quick way to get your fix or improvement slated for the next release. In general, PRs should:
- Only fix/add the functionality in question.
- Add unit tests for fixed or changed functionality.
- Address a single concern in the least number of changed lines as possible.
- Include documentation in the repo.
- Be accompanied by a complete Pull Request template (loaded automatically when a PR is created).
For changes that address core functionality or would require breaking changes (e.g. a major release), it's best to open an Issue to discuss your proposal first. This is not required but can save time creating and reviewing changes.
In general, we follow the ["fork-and-pull" Git workflow](https://github.com/susam/gitpr)
1. Fork the repository to your own Github account
2. Clone the project to your machine
3. Create a branch locally with a succinct but descriptive name
4. Commit changes to the branch
5. Following any formatting and testing guidelines specific to this repo
6. Push changes to your fork
7. Open a PR in our repository and follow the PR template so that we can efficiently review the changes.

View File

@ -0,0 +1,45 @@
# Copyright (c) 2020-present, The kubequery authors
#
# This source code is licensed as defined by the LICENSE file found in the
# root directory of this source tree.
#
# SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
FROM ubuntu:20.04 AS builder
ARG BASEQUERY_VERSION=5.0.2
ADD https://uptycs-basequery.s3.amazonaws.com/${BASEQUERY_VERSION}/basequery_${BASEQUERY_VERSION}-1.linux_amd64.deb /tmp/basequery.deb
RUN dpkg -i /tmp/basequery.deb
# =====
FROM uptycs/busybox:v1.33.0
ARG BASEQUERY_VERSION
ARG KUBEQUERY_VERSION
LABEL \
name="kubequery" \
description="kubequery powered by Osquery" \
version="${KUBEQUERY_VERSION}" \
url="https://github.com/Uptycs/kubequery"
# uptycs/busybox comes with this user predefined. We need a non-root user
USER uptycs
WORKDIR /opt/uptycs
RUN set -ex; \
mkdir /opt/uptycs/bin /opt/uptycs/etc /opt/uptycs/logs /opt/uptycs/var && \
echo "/opt/uptycs/bin/kubequery.ext" > /opt/uptycs/etc/autoload.exts
COPY --from=0 --chown=uptycs:uptycs /opt/osquery/bin/osqueryd /opt/uptycs/bin/basequery
COPY --from=0 --chown=uptycs:uptycs /opt/osquery/share/osquery/certs/certs.pem /opt/uptycs/etc/
COPY --chown=uptycs:uptycs bin/entrypoint.sh bin/kubequeryi bin/uuidgen /opt/uptycs/bin/
COPY --chown=uptycs:uptycs bin/kubequery /opt/uptycs/bin/kubequery.ext
ENV KUBEQUERY_VERSION=${KUBEQUERY_VERSION}
ENTRYPOINT ["/opt/uptycs/bin/entrypoint.sh"]

View File

@ -0,0 +1,9 @@
# License
By contributing to kubequery you agree that your contributions will be licensed
under the terms of both the [LICENSE-Apache-2.0](LICENSE-Apache-2.0) and the
[LICENSE-GPL-2.0](LICENSE-GPL-2.0) files in the root of this source tree.
If you're using kubequery you are free to choose one of the provided licenses.
`SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-only`

View File

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@ -0,0 +1,55 @@
#!/usr/bin/make -f
# Copyright (c) 2020-present, The kubequery authors
#
# This source code is licensed as defined by the LICENSE file found in the
# root directory of this source tree.
#
# SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
ifeq ($(VERSION),)
VERSION := $(shell git describe --tags HEAD | cut -d'-' -f1-2 | sed 's/-/./')
endif
all: deps lint test build kubequery.yaml
deps:
@go mod download
lint:
@go install honnef.co/go/tools/cmd/staticcheck@latest
@go install golang.org/x/lint/golint
@staticcheck ./...
@golint ./...
build: deps
@go build -ldflags="-s -w -X main.VERSION=${VERSION}" -o bin ./...
test:
@go test -race -cover ./...
integration:
@node integration/index.js
docker: build
@docker build --build-arg KUBEQUERY_VERSION=${VERSION} -t uptycs/kubequery:${VERSION} .
genschema: build
@./bin/gentables > docs/tables.json
@echo "\`\`\`sql" > docs/schema.md
@./bin/genschema >> docs/schema.md
@echo "\`\`\`" >> docs/schema.md
kubequery.yaml:
@sed -e "s/^/ /g" etc/kubequery.flags > etc/kubequery.flags.tmp
@sed -e "s/^/ /g" etc/kubequery.conf > etc/kubequery.conf.tmp
@sed -e "/kubequery.flags: |/r etc/kubequery.flags.tmp" \
-e "/kubequery.conf: |/r etc/kubequery.conf.tmp" \
-e "s/version: latest/version: ${VERSION}/g" \
kubequery-template.yaml > kubequery.yaml
@rm -f etc/*.tmp
clean:
@rm -rf vendor kubequery.yaml bin/kubequery bin/genschema bin/uuidgen etc/*.tmp
.PHONY: all integration

View File

@ -0,0 +1,180 @@
[![Build](https://github.com/Uptycs/kubequery/workflows/Build/badge.svg?branch=master)](https://github.com/Uptycs/kubequery/actions?query=workflow%3ABuild)
[![CodeQL](https://github.com/Uptycs/kubequery/workflows/CodeQL/badge.svg?branch=master)](https://github.com/Uptycs/kubequery/actions?query=workflow%3ACodeQL)
[![Go Report Card](https://goreportcard.com/badge/github.com/Uptycs/kubequery)](https://goreportcard.com/report/github.com/Uptycs/kubequery)
[![FOSSA Status](https://app.fossa.com/api/projects/custom%2B22616%2Fgit%40github.com%3AUptycs%2Fkubequery.git.svg?type=shield)](https://app.fossa.com/projects/custom%2B22616%2Fgit%40github.com%3AUptycs%2Fkubequery.git?ref=badge_shield) [![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-v2.0%20adopted-ff69b4.svg)](CODE_OF_CONDUCT.md)
---
# kubequery powered by Osquery
kubequery is a [Osquery](https://osquery.io) extension that provides SQL based analytics for [Kubernetes](https://kubernetes.io) clusters
kubequery will be packaged as docker image available from [dockerhub](https://hub.docker.com/r/uptycs/kubequery). It is expected to be deployed as a [Kubernetes Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment) per cluster. A sample deployment template is available [here](kubequery-template.yaml)
kubequery tables [schema is available here](docs/schema.md)
---
## Build
`Go 1.17` and `make` are required to build kubequery. Run: `make`
Container image for master branch will be available on [dockerhub](https://hub.docker.com/r/uptycs/kubequery)
```sh
docker pull uptycs/kubequery:latest
```
For production, tagged container images should be used instead of `latest`.
---
## Deployment
[kubequery-template.yaml](kubequery-template.yaml) is a template that creates the following Kubernetes resources:
* [Namespace](https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/)
* [ServiceAccount](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#service-account-tokens)
* [ClusterRole](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#role-and-clusterrole)
* [ClusterRoleBinding](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#rolebinding-and-clusterrolebinding)
* [ConfigMap](https://kubernetes.io/docs/concepts/configuration/configmap/)
* [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)
`kubequery` Namespace will be the placeholder for all resources that are namespaced.
`kubequery-sa` is ServiceAccount that is associated with the kubequery deployment pod specification. The container uses the service account token to authenticate with the API server.
`kubequery-clusterrole` is a ClusterRole that allows `get` and `list` operations on all resources in the following API groups:
- "" (core)
- admissionregistration&#46;k8s&#46;io
- apps
- autoscaling
- batch
- networking&#46;k8s&#46;io
- policy
- rbac&#46;authorization&#46;k8s&#46;io
- storage&#46;k8s&#46;io
`kubequery-clusterrolebinding` is a ClusterRoleBinding that binds the cluster role with the service account.
`kubequery-config` is a ConfigMap that will be mounted inside the container image as a directory. The contents of this config map should be similar to `/etc/osquery`. For example, kubequery.flags, kubequery.conf, etc. should be part of this config map.
`kubequery` is the Deployment that creates one replica pod. The container launched as a part of the pod is run as non-root user.
By default pod resource `requests` and `limits` are set to 500m (half a core) and 200MB. kubequery.yaml file should be tweaked to suite your needs before applying:
```sh
kubectl apply -f kubequery.yaml
```
Check the status of the pod using the following command. Pod should be in Running Status.
```sh
kubectl get pods -n kubequery
```
Validate the installation was successful by first executing:
```sh
kubectl exec -it $(kubectl get pods -n kubequery -o jsonpath='{.items[0].metadata.name}') -n kubequery -- kubequeryi '.tables'
```
Which should produce the following output:
```
=> kubernetes_api_resources
=> kubernetes_cluster_role_binding_subjects
=> kubernetes_cluster_role_policy_rule
=> kubernetes_config_maps
=> kubernetes_cron_jobs
=> kubernetes_csi_drivers
=> kubernetes_csi_node_drivers
=> kubernetes_daemon_set_containers
...
```
Queries can be run using kubequeryi on the deployed container:
```sh
kubectl exec -it $(kubectl get pods -n kubequery -o jsonpath='{.items[0].metadata.name}') -n kubequery -- kubequeryi --line 'SELECT * FROM kubernetes_pods'
```
Pod logs can be viewed using:
```sh
kubectl logs $(kubectl get pods -n kubequery -o jsonpath='{.items[0].metadata.name}') -n kubequery
```
## Helm
[Helm](https://helm.sh) must be installed to use the charts. Please refer to Helm's [documentation](https://helm.sh/docs) to get started.
Once Helm has been set up correctly, add the repo as follows:
```sh
helm repo add uptycs https://uptycs.github.io/kubequery
```
If you had already added this repo earlier, run `helm repo update` to retrieve the latest versions of the packages. You can then run `helm search repo uptycs` to see the charts.
To install the kubequery chart:
```sh
helm install my-kubequery uptycs/kubequery
```
To uninstall the chart:
```sh
helm delete my-kubequery
```
---
## FAQ
### Use kubequery instead of Osquery in Kubernetes?
No. kubequery should to be deployed as a [Kubernetes Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/). Which means there will be one [Pod](https://kubernetes.io/docs/concepts/workloads/pods/) of kubequery running per Kubernetes cluster. Osquery should be deployed to every node in the cluster. Querying most Osquery tables from an ephemeral pod does not provide much value. kubequery container image also runs as non-root user, which means most of the Osquery tables will either return an error or partial data.
![Deployment](docs/deployment.svg)
### Why are some columns JSON?
Normalizing nested JSON data like Kubernetes API responses will create an explosion of tables. So some of the columns in kuberenetes tables are left as JSON. Data is eventually processed by [SQLite](https://www.sqlite.org/index.html) with-in Osquery. SQLite has very [good JSON](https://www.sqlite.org/json1.html) support.
For example if `run_as_user` in `kubernetes_pod_security_policies` table looks like the following:
```json
{"rule": "MustRunAsNonRoot"}
```
To get the value of `rule`, the following query can be used:
```sql
SELECT value AS 'rule'
FROM kubernetes_pod_security_policies, json_tree(kubernetes_pod_security_policies.run_as_user)
WHERE key = 'rule';
+------------------+
| rule |
+------------------+
| MustRunAsNonRoot |
+------------------+
```
[json_each](https://www.sqlite.org/json1.html#jeach) can be used to explode JSON array types. For example if `volumes` in `kubernetes_pod_security_policies` table looks like the following:
```json
{"volumes": ["configMap","emptyDir","projected","secret","downwardAPI","persistentVolumeClaim"]}
```
To get a separate row for each volume, the following query can be used:
```sql
SELECT value
FROM kubernetes_pod_security_policies, json_each(kubernetes_pod_security_policies.volumes);
+-----------------------+
| value |
+-----------------------+
| configMap |
| emptyDir |
| projected |
| secret |
| downwardAPI |
| persistentVolumeClaim |
+-----------------------+
```
Osquery logger's like TLS, Kafka loggers can be used to export scheduled query data to remove fleet management/security analytics platforms. Lamba like functions can be applied on rows of streaming data in these platforms. These lamba functions can extract necessary fields from embedded JSON to detect compliance issues or security concerns. If tables are normalized and are streamed at different schedules, it will not be trivial to JOIN across tables and trigger events/alerts.

View File

@ -0,0 +1,15 @@
# Security Policy
## Supported Versions
| Version | Supported |
| ------- | ------------------ |
| 1.1.1 | :white_check_mark: |
| 1.1.0 | :white_check_mark: |
| 1.0.0 | :white_check_mark: |
## Reporting a Vulnerability
Please report vulnerabilties to [kubequery@uptycs.com](mailto:kubequery@uptycs.com).
We will evaluate the details and get back ASAP.
We are working on creating other communication channels for kubequery developers and users.

View File

@ -0,0 +1,28 @@
#!/bin/sh
UUID=$(/opt/uptycs/bin/uuidgen)
if [ $? -eq 0 ]; then
# Use kube-system UUID as the host identifier
ADDITIONAL_FLAGS="--host_identifier=specified --specified_identifier=${UUID}"
fi
if [ -d /opt/uptycs/config ]; then
# Copy bootstrap flags and configuration from volume mount
cp /opt/uptycs/config/* /opt/uptycs/etc/
fi
exec /opt/uptycs/bin/basequery \
--flagfile=/opt/uptycs/etc/kubequery.flags \
--config_path=/opt/uptycs/etc/kubequery.conf \
--database_path=/opt/uptycs/kubequery.db \
--logger_path=/opt/uptycs/logs \
--pidfile=/opt/uptycs/var/kubequery.pid \
--disable_watchdog \
--enroll_tables=osquery_info,kubernetes_info \
${ADDITIONAL_FLAGS} \
--tls_user_agent=kubequery/${KUBEQUERY_VERSION} \
--extensions_socket=/opt/uptycs/var/kubequery.em \
--extensions_autoload=/opt/uptycs/etc/autoload.exts \
--extensions_require=kubequery \
--extension_event_tables=kubernetes_events \
-D

View File

@ -0,0 +1,13 @@
#!/bin/sh
/opt/uptycs/bin/basequery \
--flagfile=/opt/uptycs/etc/kubequery.flags \
--config_path=/opt/uptycs/etc/kubequery.conf \
--extensions_socket=/opt/uptycs/var/kubequeryi.em \
--extensions_autoload=/opt/uptycs/etc/autoload.exts \
--extensions_require=kubequery \
--extension_event_tables=kubernetes_events \
--disable_database \
--disable_events=false \
-S \
"$@"

View File

@ -0,0 +1,34 @@
# Copyright (c) 2020-present, The kubequery authors
#
# This source code is licensed as defined by the LICENSE file found in the
# root directory of this source tree.
#
# SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/

View File

@ -0,0 +1,16 @@
# Copyright (c) 2020-present, The kubequery authors
#
# This source code is licensed as defined by the LICENSE file found in the
# root directory of this source tree.
#
# SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
apiVersion: v2
name: kubequery
description: kubequery powered by Osquery
type: application
version: 1.1.1
appVersion: 1.1.1
icon: https://raw.githubusercontent.com/Uptycs/kubequery/master/docs/kubequery.png

View File

@ -0,0 +1,55 @@
# Copyright (c) 2020-present, The kubequery authors
#
# This source code is licensed as defined by the LICENSE file found in the
# root directory of this source tree.
#
# SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
{{/*
Expand the name of the chart.
*/}}
{{- define "kubequery.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "kubequery.fullname" -}}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "kubequery.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "kubequery.labels" -}}
helm.sh/chart: {{ include "kubequery.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
app.kubernetes.io/part-of: kubequery
{{- end }}
{{/*
Selector labels
*/}}
{{- define "kubequery.selectorLabels" -}}
app.kubernetes.io/name: {{ include "kubequery.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}

View File

@ -0,0 +1,18 @@
# Copyright (c) 2020-present, The kubequery authors
#
# This source code is licensed as defined by the LICENSE file found in the
# root directory of this source tree.
#
# SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ .Release.Name }}-clusterrole
labels:
app.kubernetes.io/name: {{ .Release.Name }}-clusterrole
{{- include "kubequery.labels" . | nindent 4 }}
rules:
- apiGroups: ["", "admissionregistration.k8s.io", "apps", "autoscaling", "batch", "events.k8s.io", "networking.k8s.io", "policy", "rbac.authorization.k8s.io", "storage.k8s.io"]
resources: ["*"]
verbs: ["get", "list", "watch"]

View File

@ -0,0 +1,22 @@
# Copyright (c) 2020-present, The kubequery authors
#
# This source code is licensed as defined by the LICENSE file found in the
# root directory of this source tree.
#
# SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ .Release.Name }}-clusterrolebinding
labels:
app.kubernetes.io/name: {{ .Release.Name }}-clusterrolebinding
{{- include "kubequery.labels" . | nindent 4 }}
roleRef:
kind: ClusterRole
name: {{ .Release.Name }}-clusterrole
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: {{ .Release.Name }}-serviceaccount
namespace: {{ .Values.namespace }}

View File

@ -0,0 +1,20 @@
# Copyright (c) 2020-present, The kubequery authors
#
# This source code is licensed as defined by the LICENSE file found in the
# root directory of this source tree.
#
# SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
namespace: {{ .Values.namespace }}
labels:
app.kubernetes.io/name: {{ .Release.Name }}-configmap
{{- include "kubequery.labels" . | nindent 4 }}
data:
{{- range $name, $config := .Values.config }}
{{ $name }}: |-
{{ tpl $config $ | indent 4 }}
{{- end }}

View File

@ -0,0 +1,64 @@
# Copyright (c) 2020-present, The kubequery authors
#
# This source code is licensed as defined by the LICENSE file found in the
# root directory of this source tree.
#
# SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "kubequery.fullname" . }}
namespace: {{ .Values.namespace }}
labels:
app.kubernetes.io/name: {{ .Release.Name }}-deployment
{{- include "kubequery.labels" . | nindent 4 }}
spec:
replicas: 1
selector:
matchLabels:
{{- include "kubequery.selectorLabels" . | nindent 6 }}
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "kubequery.selectorLabels" . | nindent 8 }}
spec:
hostname: {{ .Values.cluster }}
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
terminationGracePeriodSeconds: 10
serviceAccountName: {{ .Release.Name }}-serviceaccount
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
{{- with .Values.resources }}
resources:
{{- toYaml . | nindent 10 }}
{{- end }}
volumeMounts:
- name: config
mountPath: /opt/uptycs/config
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
volumes:
- name: config
configMap:
name: {{ .Release.Name }}-configmap

View File

@ -0,0 +1,14 @@
# Copyright (c) 2020-present, The kubequery authors
#
# This source code is licensed as defined by the LICENSE file found in the
# root directory of this source tree.
#
# SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
apiVersion: v1
kind: Namespace
metadata:
name: {{ .Values.namespace }}
labels:
app.kubernetes.io/name: {{ .Values.namespace }}
{{- include "kubequery.labels" . | nindent 4 }}

View File

@ -0,0 +1,15 @@
# Copyright (c) 2020-present, The kubequery authors
#
# This source code is licensed as defined by the LICENSE file found in the
# root directory of this source tree.
#
# SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Release.Name }}-serviceaccount
namespace: {{ .Values.namespace }}
labels:
app.kubernetes.io/name: {{ .Release.Name }}-serviceaccount
{{- include "kubequery.labels" . | nindent 4 }}

View File

@ -0,0 +1,247 @@
# Copyright (c) 2020-present, The kubequery authors
#
# This source code is licensed as defined by the LICENSE file found in the
# root directory of this source tree.
#
# SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
# Namespace to deploy into
namespace: kubequery
nameOverride: ""
fullnameOverride: ""
image:
repository: uptycs/kubequery
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion.
tag: ""
# Cluster name
cluster: mycluster
resources:
requests:
cpu: 200m
memory: 128Mi
limits:
cpu: 1000m
memory: 512Mi
# kubequery configuration
config:
# TLS enroll secret
enroll.secret: TODO
# Flags
kubequery.flags: |-
--schedule_splay_percent=50
# Config
kubequery.conf: |-
{
"schedule": {
"kubernetes_api_resources": {
"query": "SELECT * FROM kubernetes_api_resources",
"interval": 43200
},
"kubernetes_cluster_role_policy_rules": {
"query": "SELECT * FROM kubernetes_cluster_role_policy_rules",
"interval": 1800
},
"kubernetes_cluster_role_binding_subjects": {
"query": "SELECT * FROM kubernetes_cluster_role_binding_subjects",
"interval": 1800
},
"kubernetes_component_statuses": {
"query": "SELECT * FROM kubernetes_component_statuses",
"interval": 3600
},
"kubernetes_config_maps": {
"query": "SELECT * FROM kubernetes_config_maps",
"interval": 600
},
"kubernetes_cron_jobs": {
"query": "SELECT * FROM kubernetes_cron_jobs",
"interval": 600
},
"kubernetes_csi_drivers": {
"query": "SELECT * FROM kubernetes_csi_drivers",
"interval": 43200
},
"kubernetes_csi_node_drivers": {
"query": "SELECT * FROM kubernetes_csi_node_drivers",
"interval": 43200
},
"kubernetes_daemon_set_containers": {
"query": "SELECT * FROM kubernetes_daemon_set_containers",
"interval": 600
},
"kubernetes_daemon_sets": {
"query": "SELECT * FROM kubernetes_daemon_sets",
"interval": 600
},
"kubernetes_daemon_set_volumes": {
"query": "SELECT * FROM kubernetes_daemon_set_volumes",
"interval": 600
},
"kubernetes_deployments": {
"query": "SELECT * FROM kubernetes_deployments",
"interval": 600
},
"kubernetes_deployments_containers": {
"query": "SELECT * FROM kubernetes_deployments_containers",
"interval": 600
},
"kubernetes_deployments_volumes": {
"query": "SELECT * FROM kubernetes_deployments_volumes",
"interval": 600
},
"kubernetes_endpoint_subsets": {
"query": "SELECT * FROM kubernetes_endpoint_subsets",
"interval": 1800
},
"kubernetes_horizontal_pod_autoscalers": {
"query": "SELECT * FROM kubernetes_horizontal_pod_autoscalers",
"interval": 7200
},
"kubernetes_info": {
"query": "SELECT * FROM kubernetes_info",
"interval": 43200
},
"kubernetes_ingress_classes": {
"query": "SELECT * FROM kubernetes_ingress_classes",
"interval": 21600
},
"kubernetes_ingresses": {
"query": "SELECT * FROM kubernetes_ingresses",
"interval": 21600
},
"kubernetes_jobs": {
"query": "SELECT * FROM kubernetes_jobs",
"interval": 600
},
"kubernetes_limit_ranges": {
"query": "SELECT * FROM kubernetes_limit_ranges",
"interval": 21600
},
"kubernetes_mutating_webhooks": {
"query": "SELECT * FROM kubernetes_mutating_webhooks",
"interval": 7200
},
"kubernetes_namespaces": {
"query": "SELECT * FROM kubernetes_namespaces",
"interval": 3600
},
"kubernetes_network_policies": {
"query": "SELECT * FROM kubernetes_network_policies",
"interval": 1800
},
"kubernetes_nodes": {
"query": "SELECT * FROM kubernetes_nodes",
"interval": 600
},
"kubernetes_persistent_volume_claims": {
"query": "SELECT * FROM kubernetes_persistent_volume_claims",
"interval": 1800
},
"kubernetes_persistent_volumes": {
"query": "SELECT * FROM kubernetes_persistent_volumes",
"interval": 1800
},
"kubernetes_pod_containers": {
"query": "SELECT * FROM kubernetes_pod_containers",
"interval": 600
},
"kubernetes_pod_disruption_budgets": {
"query": "SELECT * FROM kubernetes_pod_disruption_budgets",
"interval": 1800
},
"kubernetes_pods": {
"query": "SELECT * FROM kubernetes_pods",
"interval": 600
},
"kubernetes_pod_security_policies": {
"query": "SELECT * FROM kubernetes_pod_security_policies",
"interval": 600
},
"kubernetes_pod_template_containers": {
"query": "SELECT * FROM kubernetes_pod_template_containers",
"interval": 1800
},
"kubernetes_pod_templates": {
"query": "SELECT * FROM kubernetes_pod_templates",
"interval": 1800
},
"kubernetes_pod_templates_volumes": {
"query": "SELECT * FROM kubernetes_pod_templates_volumes",
"interval": 1800
},
"kubernetes_pod_volumes": {
"query": "SELECT * FROM kubernetes_pod_volumes",
"interval": 600
},
"kubernetes_replica_set_containers": {
"query": "SELECT * FROM kubernetes_replica_set_containers",
"interval": 600
},
"kubernetes_replica_sets": {
"query": "SELECT * FROM kubernetes_replica_sets",
"interval": 600
},
"kubernetes_replica_set_volumes": {
"query": "SELECT * FROM kubernetes_replica_set_volumes",
"interval": 600
},
"kubernetes_resource_quotas": {
"query": "SELECT * FROM kubernetes_resource_quotas",
"interval": 3600
},
"kubernetes_role_binding_subjects": {
"query": "SELECT * FROM kubernetes_role_binding_subjects",
"interval": 600
},
"kubernetes_role_policy_rules": {
"query": "SELECT * FROM kubernetes_role_policy_rules",
"interval": 600
},
"kubernetes_secrets": {
"query": "SELECT * FROM kubernetes_secrets",
"interval": 600
},
"kubernetes_service_accounts": {
"query": "SELECT * FROM kubernetes_service_accounts",
"interval": 600
},
"kubernetes_services": {
"query": "SELECT * FROM kubernetes_services",
"interval": 900
},
"kubernetes_stateful_set_containers": {
"query": "SELECT * FROM kubernetes_stateful_set_containers",
"interval": 600
},
"kubernetes_stateful_sets": {
"query": "SELECT * FROM kubernetes_stateful_sets",
"interval": 600
},
"kubernetes_stateful_set_volumes": {
"query": "SELECT * FROM kubernetes_stateful_set_volumes",
"interval": 600
},
"kubernetes_storage_classes": {
"query": "SELECT * FROM kubernetes_storage_classes",
"interval": 21600
},
"kubernetes_validating_webhooks": {
"query": "SELECT * FROM kubernetes_validating_webhooks",
"interval": 7200
},
"kubernetes_volume_attachments": {
"query": "SELECT * FROM kubernetes_volume_attachments",
"interval": 3600
}
},
"options":{
}
}

View File

@ -0,0 +1,30 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package main
import (
"fmt"
"github.com/Uptycs/kubequery/internal/k8s/tables"
)
func main() {
for _, t := range tables.GetTables() {
fmt.Printf("CREATE TABLE %s (\n", t.Name)
for i, c := range t.Columns {
fmt.Printf(" `%s` %s", c.Name, c.Type)
if i < len(t.Columns)-1 {
fmt.Printf(",")
}
fmt.Println()
}
fmt.Print(");\n\n")
}
}

View File

@ -0,0 +1,39 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package main
import (
"fmt"
"github.com/Uptycs/kubequery/internal/k8s/tables"
)
func main() {
tbls := tables.GetTables()
fmt.Printf("{\n \"tables\": [")
for j, t := range tbls {
fmt.Printf(" {\n \"name\": \"%s\",\n \"columns\": [\n", t.Name)
for i, c := range t.Columns {
fmt.Printf(" {\n \"name\": \"%s\",\n \"type\": \"%s\"\n", c.Name, c.Type)
if i < len(t.Columns)-1 {
fmt.Printf(" },\n")
} else {
fmt.Printf(" }\n")
}
}
fmt.Printf(" ]\n")
if j < len(tbls)-1 {
fmt.Printf(" },\n")
} else {
fmt.Printf(" }\n")
}
}
fmt.Printf(" ]\n}")
}

View File

@ -0,0 +1,98 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package main
import (
"context"
"flag"
"fmt"
"os"
"os/signal"
"syscall"
"time"
osquery "github.com/Uptycs/basequery-go"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/Uptycs/kubequery/internal/k8s"
"github.com/Uptycs/kubequery/internal/k8s/event"
"github.com/Uptycs/kubequery/internal/k8s/tables"
)
var (
// VERSION set by compiler
VERSION = "latest"
//lint:ignore U1000 Argument is required by basequery
verbose = flag.Bool("verbose", false, "Whether to enable verbose logging")
version = flag.Bool("version", false, "Prints kubequery version")
socket = flag.String("socket", "", "Path to the extensions UNIX domain socket")
timeout = flag.Int("timeout", 5, "Seconds to wait for autoloaded extensions")
interval = flag.Int("interval", 5, "Seconds delay between connectivity checks")
)
func main() {
flag.Parse()
if *version {
fmt.Println("kubequery version:", VERSION)
os.Exit(0)
}
if *socket == "" {
panic("Missing required --socket argument")
}
err := k8s.Init()
if err != nil {
panic(fmt.Sprintf("Error connecting to kubernetes API server: %s", err))
}
server, err := osquery.NewExtensionManagerServer(
"kubequery",
*socket,
osquery.ServerVersion(VERSION),
osquery.ServerTimeout(time.Second*time.Duration(*timeout)),
osquery.ServerPingInterval(time.Second*time.Duration(*interval)),
)
if err != nil {
panic(fmt.Sprintf("Error launching kubequery: %s", err))
}
quit := make(chan os.Signal, 1)
signal.Notify(quit, os.Interrupt)
for _, t := range tables.GetTables() {
server.RegisterPlugin(table.NewPlugin(t.Name, t.Columns, t.GenFunc))
}
go func() {
if err := server.Run(); err != nil {
panic(fmt.Sprintf("Failed to start extension manager server: %s", err))
}
syscall.Kill(syscall.Getpid(), syscall.SIGINT)
}()
// Wait for the extension manager to start before sending events
time.Sleep(time.Second * 5)
watcher, err := event.CreateEventWatcher(*socket, time.Second*time.Duration(*timeout))
if err != nil {
fmt.Println("Failed to create kubernetes event watcher: ", err)
} else {
watcher.Start()
}
<-quit
if watcher != nil {
watcher.Stop()
}
server.Shutdown(context.Background())
}

View File

@ -0,0 +1,33 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package main
import (
"context"
"fmt"
"github.com/Uptycs/kubequery/internal/k8s"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func main() {
err := k8s.Init()
if err != nil {
panic(fmt.Sprintf("Error connecting to kubernetes API server: %s", err))
}
options := v1.GetOptions{}
ks, err := k8s.GetClient().CoreV1().Namespaces().Get(context.Background(), "kube-system", options)
if err != nil {
panic(fmt.Sprintf("Error getting kube-system namespace: %s", err))
}
fmt.Print(ks.ObjectMeta.UID)
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,206 @@
{
"schedule": {
"kubernetes_api_resources": {
"query": "SELECT * FROM kubernetes_api_resources",
"interval": 43200
},
"kubernetes_cluster_role_policy_rules": {
"query": "SELECT * FROM kubernetes_cluster_role_policy_rules",
"interval": 1800
},
"kubernetes_cluster_role_binding_subjects": {
"query": "SELECT * FROM kubernetes_cluster_role_binding_subjects",
"interval": 1800
},
"kubernetes_component_statuses": {
"query": "SELECT * FROM kubernetes_component_statuses",
"interval": 3600
},
"kubernetes_config_maps": {
"query": "SELECT * FROM kubernetes_config_maps",
"interval": 600
},
"kubernetes_cron_jobs": {
"query": "SELECT * FROM kubernetes_cron_jobs",
"interval": 600
},
"kubernetes_csi_drivers": {
"query": "SELECT * FROM kubernetes_csi_drivers",
"interval": 43200
},
"kubernetes_csi_node_drivers": {
"query": "SELECT * FROM kubernetes_csi_node_drivers",
"interval": 43200
},
"kubernetes_daemon_set_containers": {
"query": "SELECT * FROM kubernetes_daemon_set_containers",
"interval": 600
},
"kubernetes_daemon_sets": {
"query": "SELECT * FROM kubernetes_daemon_sets",
"interval": 600
},
"kubernetes_daemon_set_volumes": {
"query": "SELECT * FROM kubernetes_daemon_set_volumes",
"interval": 600
},
"kubernetes_deployments": {
"query": "SELECT * FROM kubernetes_deployments",
"interval": 600
},
"kubernetes_deployments_containers": {
"query": "SELECT * FROM kubernetes_deployments_containers",
"interval": 600
},
"kubernetes_deployments_volumes": {
"query": "SELECT * FROM kubernetes_deployments_volumes",
"interval": 600
},
"kubernetes_endpoint_subsets": {
"query": "SELECT * FROM kubernetes_endpoint_subsets",
"interval": 1800
},
"kubernetes_horizontal_pod_autoscalers": {
"query": "SELECT * FROM kubernetes_horizontal_pod_autoscalers",
"interval": 7200
},
"kubernetes_info": {
"query": "SELECT * FROM kubernetes_info",
"interval": 43200
},
"kubernetes_ingress_classes": {
"query": "SELECT * FROM kubernetes_ingress_classes",
"interval": 21600
},
"kubernetes_ingresses": {
"query": "SELECT * FROM kubernetes_ingresses",
"interval": 21600
},
"kubernetes_jobs": {
"query": "SELECT * FROM kubernetes_jobs",
"interval": 600
},
"kubernetes_limit_ranges": {
"query": "SELECT * FROM kubernetes_limit_ranges",
"interval": 21600
},
"kubernetes_mutating_webhooks": {
"query": "SELECT * FROM kubernetes_mutating_webhooks",
"interval": 7200
},
"kubernetes_namespaces": {
"query": "SELECT * FROM kubernetes_namespaces",
"interval": 3600
},
"kubernetes_network_policies": {
"query": "SELECT * FROM kubernetes_network_policies",
"interval": 1800
},
"kubernetes_nodes": {
"query": "SELECT * FROM kubernetes_nodes",
"interval": 600
},
"kubernetes_persistent_volume_claims": {
"query": "SELECT * FROM kubernetes_persistent_volume_claims",
"interval": 1800
},
"kubernetes_persistent_volumes": {
"query": "SELECT * FROM kubernetes_persistent_volumes",
"interval": 1800
},
"kubernetes_pod_containers": {
"query": "SELECT * FROM kubernetes_pod_containers",
"interval": 600
},
"kubernetes_pod_disruption_budgets": {
"query": "SELECT * FROM kubernetes_pod_disruption_budgets",
"interval": 1800
},
"kubernetes_pods": {
"query": "SELECT * FROM kubernetes_pods",
"interval": 600
},
"kubernetes_pod_security_policies": {
"query": "SELECT * FROM kubernetes_pod_security_policies",
"interval": 600
},
"kubernetes_pod_template_containers": {
"query": "SELECT * FROM kubernetes_pod_template_containers",
"interval": 1800
},
"kubernetes_pod_templates": {
"query": "SELECT * FROM kubernetes_pod_templates",
"interval": 1800
},
"kubernetes_pod_templates_volumes": {
"query": "SELECT * FROM kubernetes_pod_templates_volumes",
"interval": 1800
},
"kubernetes_pod_volumes": {
"query": "SELECT * FROM kubernetes_pod_volumes",
"interval": 600
},
"kubernetes_replica_set_containers": {
"query": "SELECT * FROM kubernetes_replica_set_containers",
"interval": 600
},
"kubernetes_replica_sets": {
"query": "SELECT * FROM kubernetes_replica_sets",
"interval": 600
},
"kubernetes_replica_set_volumes": {
"query": "SELECT * FROM kubernetes_replica_set_volumes",
"interval": 600
},
"kubernetes_resource_quotas": {
"query": "SELECT * FROM kubernetes_resource_quotas",
"interval": 3600
},
"kubernetes_role_binding_subjects": {
"query": "SELECT * FROM kubernetes_role_binding_subjects",
"interval": 600
},
"kubernetes_role_policy_rules": {
"query": "SELECT * FROM kubernetes_role_policy_rules",
"interval": 600
},
"kubernetes_secrets": {
"query": "SELECT * FROM kubernetes_secrets",
"interval": 600
},
"kubernetes_service_accounts": {
"query": "SELECT * FROM kubernetes_service_accounts",
"interval": 600
},
"kubernetes_services": {
"query": "SELECT * FROM kubernetes_services",
"interval": 900
},
"kubernetes_stateful_set_containers": {
"query": "SELECT * FROM kubernetes_stateful_set_containers",
"interval": 600
},
"kubernetes_stateful_sets": {
"query": "SELECT * FROM kubernetes_stateful_sets",
"interval": 600
},
"kubernetes_stateful_set_volumes": {
"query": "SELECT * FROM kubernetes_stateful_set_volumes",
"interval": 600
},
"kubernetes_storage_classes": {
"query": "SELECT * FROM kubernetes_storage_classes",
"interval": 21600
},
"kubernetes_validating_webhooks": {
"query": "SELECT * FROM kubernetes_validating_webhooks",
"interval": 7200
},
"kubernetes_volume_attachments": {
"query": "SELECT * FROM kubernetes_volume_attachments",
"interval": 3600
}
},
"options":{
}
}

View File

@ -0,0 +1,2 @@
--disable_events_staging=true
--schedule_splay_percent=50

View File

@ -0,0 +1,9 @@
--schedule_splay_percent=50
--disable_watchdog=true
--tls_hostname=z6c0b1jca0.execute-api.us-west-2.amazonaws.com
--tls_server_certs=/opt/uptycs/etc/certs.pem
--enroll_secret_path=/opt/uptycs/config/enroll.secret
--enroll_tls_endpoint=/default/enroll
--logger_plugin=tls
--logger_tls_endpoint=/default/log
--logger_tls_compress=true

View File

@ -0,0 +1,58 @@
module github.com/Uptycs/kubequery
go 1.17
require (
github.com/Uptycs/basequery-go v0.8.0
github.com/google/uuid v1.3.0
github.com/iancoleman/strcase v0.2.0
github.com/stretchr/testify v1.7.0
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616
k8s.io/api v0.22.4
k8s.io/apimachinery v0.22.4
k8s.io/client-go v0.22.4
)
require (
github.com/Microsoft/go-winio v0.5.1 // indirect
github.com/apache/thrift v0.15.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/evanphx/json-patch v4.11.0+incompatible // indirect
github.com/go-logr/logr v1.2.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/go-cmp v0.5.6 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/googleapis/gnostic v0.5.5 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.11.0 // indirect
github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.32.1 // indirect
github.com/prometheus/procfs v0.7.3 // indirect
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/net v0.0.0-20211205041911-012df41ee64c // indirect
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d // indirect
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 // indirect
golang.org/x/tools v0.1.7 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.27.1 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
k8s.io/klog/v2 v2.30.0 // indirect
k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c // indirect
k8s.io/utils v0.0.0-20211203121628-587287796c64 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.0 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)

View File

@ -0,0 +1,647 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA=
github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M=
github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY=
github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/Uptycs/basequery-go v0.8.0 h1:a1g1ikKKOCnHGzqxfiXsvquUJU5hNcZkjtfTJXcEKcg=
github.com/Uptycs/basequery-go v0.8.0/go.mod h1:U46Bme4Zi+bKG+wYVw2XFfk3bHs0WWzpWQ2R+ivgEd4=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/apache/thrift v0.14.2/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/apache/thrift v0.15.0 h1:aGvdaR0v1t9XLgjtBYwxcBvBOTMqClzwE26CHOgjW1Y=
github.com/apache/thrift v0.15.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/evanphx/json-patch v4.11.0+incompatible h1:glyUF9yIYtMHzn8xaKw5rMhdWcwsYV8dZHIq5567/xs=
github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.1 h1:DX7uPQ4WgAWfoh+NGGlbJQswnYIVvz0SRlLS3rPZQDA=
github.com/go-logr/logr v1.2.1/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU=
github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw=
github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/iancoleman/strcase v0.2.0 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHLwW0=
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA=
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ=
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4=
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211205041911-012df41ee64c h1:7SfqwP5fxEtl/P02w5IhKc86ziJ+A25yFrkVgoy2FT8=
golang.org/x/net v0.0.0-20211205041911-012df41ee64c/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg=
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d h1:FjkYO/PPp4Wi0EAUOVLxePm7qVW4r4ctbWpURyuOD0E=
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 h1:GZokNIeuVkl3aZHJchRrr13WCsols02MLUcz1U9is6M=
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ=
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
k8s.io/api v0.22.4 h1:UvyHW0ezB2oIgHAxlYoo6UJQObYXU7awuNarwoHEOjw=
k8s.io/api v0.22.4/go.mod h1:Rgs+9gIGYC5laXQSZZ9JqT5NevNgoGiOdVWi1BAB3qk=
k8s.io/apimachinery v0.22.4 h1:9uwcvPpukBw/Ri0EUmWz+49cnFtaoiyEhQTK+xOe7Ck=
k8s.io/apimachinery v0.22.4/go.mod h1:yU6oA6Gnax9RrxGzVvPFFJ+mpnW6PBSqp0sx0I0HHW0=
k8s.io/client-go v0.22.4 h1:aAQ1Wk+I3bjCNk35YWUqbaueqrIonkfDPJSPDDe8Kfg=
k8s.io/client-go v0.22.4/go.mod h1:Yzw4e5e7h1LNHA4uqnMVrpEpUs1hJOiuBsJKIlRCHDA=
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec=
k8s.io/klog/v2 v2.30.0 h1:bUO6drIvCIsvZ/XFgfxoGFQU/a4Qkh0iAlvUR7vlHJw=
k8s.io/klog/v2 v2.30.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c h1:jvamsI1tn9V0S8jicyX82qaFC0H/NKxv2e5mbqsgR80=
k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw=
k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
k8s.io/utils v0.0.0-20211203121628-587287796c64 h1:EzpFOlqWaj9Qbd/q4TqWSSpaQ/3p30lV1hGvcMYKLWc=
k8s.io/utils v0.0.0-20211203121628-587287796c64/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
sigs.k8s.io/structured-merge-diff/v4 v4.2.0 h1:kDvPBbnPk+qYmkHmSo8vKGp438IASWofnbbUKDE/bv0=
sigs.k8s.io/structured-merge-diff/v4 v4.2.0/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=

View File

@ -0,0 +1,94 @@
'use strict';
const util = require('util');
const execFile = util.promisify(require('child_process').execFile);
const EXEC_OPTIONS = { timeout: 10000, maxBuffer: 10 * 1024 * 1024 };
const TABLES = [
'api_resources',
'cluster_role_binding_subjects',
'cluster_role_policy_rules',
'component_statuses',
'config_maps',
'cron_jobs',
'csi_drivers',
'csi_node_drivers',
'daemon_set_containers',
'daemon_set_volumes',
'daemon_sets',
'deployments',
'deployments_containers',
'deployments_volumes',
'endpoint_subsets',
'events',
'horizontal_pod_autoscalers',
'info',
'ingress_classes',
'ingresses',
'jobs',
'limit_ranges',
'mutating_webhooks',
'namespaces',
'network_policies',
'nodes',
'persistent_volume_claims',
'persistent_volumes',
'pod_containers',
'pod_disruption_budgets',
'pod_security_policies',
'pod_template_containers',
'pod_templates',
'pod_templates_volumes',
'pod_volumes',
'pods',
'replica_set_containers',
'replica_set_volumes',
'replica_sets',
'resource_quotas',
'role_binding_subjects',
'role_policy_rules',
'secrets',
'service_accounts',
'services',
'stateful_set_containers',
'stateful_set_volumes',
'stateful_sets',
'storage_classes',
'validating_webhooks',
'volume_attachments'
];
async function getPodName() {
const { stdout, stderr } = await execFile('kubectl', ['get', 'pods', '-n', 'kubequery', '-o', "jsonpath={.items[0].metadata.name}"], EXEC_OPTIONS);
if (stdout) {
return stdout;
}
throw new Error('Failed to get kubequery pod name');
}
async function executeSQL(podName, sql) {
const { stdout, stderr } = await execFile('kubectl', ['exec', '-it', podName, '-n', 'kubequery', '--', 'sh', '-c', `kubequeryi --json '${sql}'`], EXEC_OPTIONS);
if (stdout) {
return stdout;
}
throw new Error('Failed to execute SQL: ' + sql + '. Error: ' + stderr);
}
(async () => {
try {
const podName = await getPodName();
for (const table of TABLES) {
const output = await executeSQL(podName, 'SELECT * FROM kubernetes_' + table);
console.assert(output !== '', 'Invalid output for table: ' + table);
const json = JSON.parse(output);
console.assert(Array.isArray(json), 'Table output is not an array: ' + table);
console.info(table + ': ' + json.length);
}
} catch (err) {
console.error(err);
process.exit(1);
}
})();

View File

@ -0,0 +1,62 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package admissionregistration
import (
"context"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/Uptycs/kubequery/internal/k8s"
v1 "k8s.io/api/admissionregistration/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
)
type mutatingWebhook struct {
ClusterName string
ClusterUID types.UID
v1.MutatingWebhook
}
// MutatingWebhookColumns returns kubernetes mutating webhook fields as Osquery table columns.
func MutatingWebhookColumns() []table.ColumnDefinition {
return k8s.GetSchema(&mutatingWebhook{})
}
// MutatingWebhooksGenerate generates the mutating webhook Osquery table data.
func MutatingWebhooksGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
options := metav1.ListOptions{}
results := make([]map[string]string, 0)
for {
mwcs, err := k8s.GetClient().AdmissionregistrationV1().MutatingWebhookConfigurations().List(ctx, options)
if err != nil {
return nil, err
}
for _, mwc := range mwcs.Items {
for _, mw := range mwc.Webhooks {
item := &mutatingWebhook{
ClusterName: k8s.GetClusterName(),
ClusterUID: k8s.GetClusterUID(),
MutatingWebhook: mw,
}
results = append(results, k8s.ToMap(item))
}
}
if mwcs.Continue == "" {
break
}
options.Continue = mwcs.Continue
}
return results, nil
}

View File

@ -0,0 +1,56 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package admissionregistration
import (
"context"
"testing"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/Uptycs/kubequery/internal/k8s"
"github.com/stretchr/testify/assert"
v1 "k8s.io/api/admissionregistration/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes/fake"
)
func TestMutatingWebhooksGenerate(t *testing.T) {
i32 := int32(123)
url := string("https://www.google.com")
k8s.SetClient(fake.NewSimpleClientset(&v1.MutatingWebhookConfiguration{
Webhooks: []v1.MutatingWebhook{
{
Name: "mw1",
TimeoutSeconds: &i32,
ClientConfig: v1.WebhookClientConfig{URL: &url},
},
{
Name: "mw2",
TimeoutSeconds: &i32,
ClientConfig: v1.WebhookClientConfig{URL: &url},
},
},
}), types.UID(""), "")
mws, err := MutatingWebhooksGenerate(context.TODO(), table.QueryContext{})
assert.Nil(t, err)
assert.Equal(t, []map[string]string{
{
"name": "mw1",
"timeout_seconds": "123",
"client_config": "{\"url\":\"https://www.google.com\"}",
},
{
"name": "mw2",
"timeout_seconds": "123",
"client_config": "{\"url\":\"https://www.google.com\"}",
},
}, mws)
}

View File

@ -0,0 +1,62 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package admissionregistration
import (
"context"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/Uptycs/kubequery/internal/k8s"
v1 "k8s.io/api/admissionregistration/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
)
type validatingWebhook struct {
ClusterName string
ClusterUID types.UID
v1.ValidatingWebhook
}
// ValidatingWebhookColumns returns kubernetes validating webhook fields as Osquery table columns.
func ValidatingWebhookColumns() []table.ColumnDefinition {
return k8s.GetSchema(&validatingWebhook{})
}
// ValidatingWebhooksGenerate generates the kubernetes validating webhooks as Osquery table data.
func ValidatingWebhooksGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
options := metav1.ListOptions{}
results := make([]map[string]string, 0)
for {
vwcs, err := k8s.GetClient().AdmissionregistrationV1().ValidatingWebhookConfigurations().List(ctx, options)
if err != nil {
return nil, err
}
for _, vwc := range vwcs.Items {
for _, vw := range vwc.Webhooks {
item := &validatingWebhook{
ClusterName: k8s.GetClusterName(),
ClusterUID: k8s.GetClusterUID(),
ValidatingWebhook: vw,
}
results = append(results, k8s.ToMap(item))
}
}
if vwcs.Continue == "" {
break
}
options.Continue = vwcs.Continue
}
return results, nil
}

View File

@ -0,0 +1,56 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package admissionregistration
import (
"context"
"testing"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/Uptycs/kubequery/internal/k8s"
"github.com/stretchr/testify/assert"
v1 "k8s.io/api/admissionregistration/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes/fake"
)
func TestValidatingWebhooksGenerate(t *testing.T) {
i32 := int32(123)
url := string("https://www.google.com")
k8s.SetClient(fake.NewSimpleClientset(&v1.ValidatingWebhookConfiguration{
Webhooks: []v1.ValidatingWebhook{
{
Name: "vw1",
TimeoutSeconds: &i32,
ClientConfig: v1.WebhookClientConfig{URL: &url},
},
{
Name: "vw2",
TimeoutSeconds: &i32,
ClientConfig: v1.WebhookClientConfig{URL: &url},
},
},
}), types.UID(""), "")
mws, err := ValidatingWebhooksGenerate(context.TODO(), table.QueryContext{})
assert.Nil(t, err)
assert.Equal(t, []map[string]string{
{
"name": "vw1",
"timeout_seconds": "123",
"client_config": "{\"url\":\"https://www.google.com\"}",
},
{
"name": "vw2",
"timeout_seconds": "123",
"client_config": "{\"url\":\"https://www.google.com\"}",
},
}, mws)
}

View File

@ -0,0 +1,175 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package apps
import (
"context"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/Uptycs/kubequery/internal/k8s"
v1 "k8s.io/api/apps/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type daemonSet struct {
k8s.CommonNamespacedFields
k8s.CommonPodFields
v1.DaemonSetStatus
Selector *metav1.LabelSelector
UpdateStrategy v1.DaemonSetUpdateStrategy
MinReadySeconds int32
RevisionHistoryLimit *int32
}
// DaemonSetColumns returns kubernetes daemon set fields as Osquery table columns.
func DaemonSetColumns() []table.ColumnDefinition {
return k8s.GetSchema(&daemonSet{})
}
// DaemonSetsGenerate generates the kubernetes daemon sets as Osquery table data.
func DaemonSetsGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
options := metav1.ListOptions{}
results := make([]map[string]string, 0)
for {
dss, err := k8s.GetClient().AppsV1().DaemonSets(metav1.NamespaceAll).List(ctx, options)
if err != nil {
return nil, err
}
for _, ds := range dss.Items {
item := &daemonSet{
CommonNamespacedFields: k8s.GetCommonNamespacedFields(ds.ObjectMeta),
CommonPodFields: k8s.GetCommonPodFields(ds.Spec.Template.Spec),
DaemonSetStatus: ds.Status,
Selector: ds.Spec.Selector,
UpdateStrategy: ds.Spec.UpdateStrategy,
MinReadySeconds: ds.Spec.MinReadySeconds,
RevisionHistoryLimit: ds.Spec.RevisionHistoryLimit,
}
results = append(results, k8s.ToMap(item))
}
if dss.Continue == "" {
break
}
options.Continue = dss.Continue
}
return results, nil
}
type daemonSetContainer struct {
k8s.CommonNamespacedFields
k8s.CommonContainerFields
DaemonSetName string
ContainerType string
}
// DaemonSetContainerColumns returns kubernetes daemon set container fields as Osquery table columns.
func DaemonSetContainerColumns() []table.ColumnDefinition {
return k8s.GetSchema(&daemonSetContainer{})
}
// DaemonSetContainersGenerate generates the kubernetes daemon set containers as Osquery table data.
func DaemonSetContainersGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
options := metav1.ListOptions{}
results := make([]map[string]string, 0)
for {
dss, err := k8s.GetClient().AppsV1().DaemonSets(metav1.NamespaceAll).List(ctx, options)
if err != nil {
return nil, err
}
for _, ds := range dss.Items {
for _, c := range ds.Spec.Template.Spec.InitContainers {
item := &daemonSetContainer{
CommonNamespacedFields: k8s.GetParentCommonNamespacedFields(ds.ObjectMeta, c.Name),
CommonContainerFields: k8s.GetCommonContainerFields(c),
DaemonSetName: ds.Name,
ContainerType: "init",
}
item.Name = c.Name
results = append(results, k8s.ToMap(item))
}
for _, c := range ds.Spec.Template.Spec.Containers {
item := &daemonSetContainer{
CommonNamespacedFields: k8s.GetParentCommonNamespacedFields(ds.ObjectMeta, c.Name),
CommonContainerFields: k8s.GetCommonContainerFields(c),
DaemonSetName: ds.Name,
ContainerType: "container",
}
item.Name = c.Name
results = append(results, k8s.ToMap(item))
}
for _, c := range ds.Spec.Template.Spec.EphemeralContainers {
item := &daemonSetContainer{
CommonNamespacedFields: k8s.GetParentCommonNamespacedFields(ds.ObjectMeta, c.Name),
CommonContainerFields: k8s.GetCommonEphemeralContainerFields(c),
DaemonSetName: ds.Name,
ContainerType: "ephemeral",
}
item.Name = c.Name
results = append(results, k8s.ToMap(item))
}
}
if dss.Continue == "" {
break
}
options.Continue = dss.Continue
}
return results, nil
}
type daemonSetVolume struct {
k8s.CommonNamespacedFields
k8s.CommonVolumeFields
DaemonSetName string
}
// DaemonSetVolumeColumns returns kubernetes daemon set volume fields as Osquery table columns.
func DaemonSetVolumeColumns() []table.ColumnDefinition {
return k8s.GetSchema(&daemonSetVolume{})
}
// DaemonSetVolumesGenerate generates the kubernetes daemon set volumes as Osquery table data.
func DaemonSetVolumesGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
options := metav1.ListOptions{}
results := make([]map[string]string, 0)
for {
dss, err := k8s.GetClient().AppsV1().DaemonSets(metav1.NamespaceAll).List(ctx, options)
if err != nil {
return nil, err
}
for _, ds := range dss.Items {
for _, v := range ds.Spec.Template.Spec.Volumes {
item := &daemonSetVolume{
CommonNamespacedFields: k8s.GetCommonNamespacedFields(ds.ObjectMeta),
CommonVolumeFields: k8s.GetCommonVolumeFields(v),
DaemonSetName: ds.Name,
}
item.Name = v.Name
results = append(results, k8s.ToMap(item))
}
}
if dss.Continue == "" {
break
}
options.Continue = dss.Continue
}
return results, nil
}

View File

@ -0,0 +1,324 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package apps
import (
"context"
"testing"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/stretchr/testify/assert"
)
func TestDaemonSetsGenerate(t *testing.T) {
dss, err := DaemonSetsGenerate(context.TODO(), table.QueryContext{})
assert.Nil(t, err)
assert.Equal(t, []map[string]string{
{
"annotations": "{\"deprecated.daemonset.template.generation\":\"1\"}",
"cluster_uid": "blah",
"creation_timestamp": "1610476216",
"current_number_scheduled": "1",
"desired_number_scheduled": "1",
"dns_policy": "ClusterFirst",
"host_ipc": "0",
"host_network": "1",
"host_pid": "0",
"labels": "{\"k8s-app\":\"calico-node\"}",
"min_ready_seconds": "0",
"name": "calico-node",
"namespace": "kube-system",
"node_selector": "{\"kubernetes.io/os\":\"linux\"}",
"number_available": "1",
"number_misscheduled": "0",
"number_ready": "1",
"number_unavailable": "0",
"observed_generation": "1",
"priority_class_name": "system-node-critical",
"restart_policy": "Always",
"revision_history_limit": "10",
"scheduler_name": "default-scheduler",
"selector": "{\"matchLabels\":{\"k8s-app\":\"calico-node\"}}",
"service_account_name": "calico-node",
"termination_grace_period_seconds": "0",
"tolerations": "[{\"operator\":\"Exists\",\"effect\":\"NoSchedule\"},{\"key\":\"CriticalAddonsOnly\",\"operator\":\"Exists\"},{\"operator\":\"Exists\",\"effect\":\"NoExecute\"}]",
"uid": "e6fed7f0-f79a-464f-a3d2-b63247a1f590",
"update_strategy": "{\"type\":\"RollingUpdate\",\"rollingUpdate\":{\"maxUnavailable\":1}}",
"updated_number_scheduled": "1",
},
}, dss)
}
func TestDaemonSetContainersGenerate(t *testing.T) {
dss, err := DaemonSetContainersGenerate(context.TODO(), table.QueryContext{})
assert.Nil(t, err)
assert.Equal(t, []map[string]string{
{
"annotations": "{\"deprecated.daemonset.template.generation\":\"1\"}",
"cluster_uid": "blah",
"command": "[\"/opt/cni/bin/calico-ipam\",\"-upgrade\"]",
"container_type": "init",
"creation_timestamp": "1610476216",
"daemon_set_name": "calico-node",
"env": "[{\"name\":\"KUBERNETES_NODE_NAME\",\"valueFrom\":{\"fieldRef\":{\"apiVersion\":\"v1\",\"fieldPath\":\"spec.nodeName\"}}},{\"name\":\"CALICO_NETWORKING_BACKEND\",\"valueFrom\":{\"configMapKeyRef\":{\"name\":\"calico-config\",\"key\":\"calico_backend\"}}}]",
"image": "calico/cni:v3.13.2",
"image_pull_policy": "IfNotPresent",
"labels": "{\"k8s-app\":\"calico-node\"}",
"name": "upgrade-ipam",
"namespace": "kube-system",
"privileged": "1",
"stdin": "0",
"stdin_once": "0",
"termination_message_path": "/dev/termination-log",
"termination_message_policy": "File",
"tty": "0",
"uid": "8b0b4bb2-1703-551e-9e14-af10886a5eec",
"volume_mounts": "[{\"name\":\"host-local-net-dir\",\"mountPath\":\"/var/lib/cni/networks\"},{\"name\":\"cni-bin-dir\",\"mountPath\":\"/host/opt/cni/bin\"}]",
},
{
"annotations": "{\"deprecated.daemonset.template.generation\":\"1\"}",
"cluster_uid": "blah",
"command": "[\"/install-cni.sh\"]",
"container_type": "init",
"creation_timestamp": "1610476216",
"daemon_set_name": "calico-node",
"env": "[{\"name\":\"CNI_CONF_NAME\",\"value\":\"10-calico.conflist\"},{\"name\":\"CNI_NETWORK_CONFIG\",\"valueFrom\":{\"configMapKeyRef\":{\"name\":\"calico-config\",\"key\":\"cni_network_config\"}}},{\"name\":\"KUBERNETES_NODE_NAME\",\"valueFrom\":{\"fieldRef\":{\"apiVersion\":\"v1\",\"fieldPath\":\"spec.nodeName\"}}},{\"name\":\"CNI_MTU\",\"valueFrom\":{\"configMapKeyRef\":{\"name\":\"calico-config\",\"key\":\"veth_mtu\"}}},{\"name\":\"SLEEP\",\"value\":\"false\"},{\"name\":\"CNI_NET_DIR\",\"value\":\"/var/snap/microk8s/current/args/cni-network\"}]",
"image": "calico/cni:v3.13.2",
"image_pull_policy": "IfNotPresent",
"labels": "{\"k8s-app\":\"calico-node\"}",
"name": "install-cni",
"namespace": "kube-system",
"privileged": "1",
"stdin": "0",
"stdin_once": "0",
"termination_message_path": "/dev/termination-log",
"termination_message_policy": "File",
"tty": "0",
"uid": "e773308e-cb75-5c58-9d85-0b71c92f8a24",
"volume_mounts": "[{\"name\":\"cni-bin-dir\",\"mountPath\":\"/host/opt/cni/bin\"},{\"name\":\"cni-net-dir\",\"mountPath\":\"/host/etc/cni/net.d\"}]",
},
{
"annotations": "{\"deprecated.daemonset.template.generation\":\"1\"}",
"cluster_uid": "blah",
"container_type": "init",
"creation_timestamp": "1610476216",
"daemon_set_name": "calico-node",
"image": "calico/pod2daemon-flexvol:v3.13.2",
"image_pull_policy": "IfNotPresent",
"labels": "{\"k8s-app\":\"calico-node\"}",
"name": "flexvol-driver",
"namespace": "kube-system",
"privileged": "1",
"stdin": "0",
"stdin_once": "0",
"termination_message_path": "/dev/termination-log",
"termination_message_policy": "File",
"tty": "0",
"uid": "8122bba4-1bdc-562f-9a01-96345dbc3e4c",
"volume_mounts": "[{\"name\":\"flexvol-driver-host\",\"mountPath\":\"/host/driver\"}]",
},
{
"annotations": "{\"deprecated.daemonset.template.generation\":\"1\"}",
"cluster_uid": "blah",
"container_type": "container",
"creation_timestamp": "1610476216",
"daemon_set_name": "calico-node",
"env": "[{\"name\":\"DATASTORE_TYPE\",\"value\":\"kubernetes\"},{\"name\":\"WAIT_FOR_DATASTORE\",\"value\":\"true\"},{\"name\":\"NODENAME\",\"valueFrom\":{\"fieldRef\":{\"apiVersion\":\"v1\",\"fieldPath\":\"spec.nodeName\"}}},{\"name\":\"CALICO_NETWORKING_BACKEND\",\"valueFrom\":{\"configMapKeyRef\":{\"name\":\"calico-config\",\"key\":\"calico_backend\"}}},{\"name\":\"CLUSTER_TYPE\",\"value\":\"k8s,bgp\"},{\"name\":\"IP\",\"value\":\"autodetect\"},{\"name\":\"IP_AUTODETECTION_METHOD\",\"value\":\"first-found\"},{\"name\":\"CALICO_IPV4POOL_VXLAN\",\"value\":\"Always\"},{\"name\":\"FELIX_IPINIPMTU\",\"valueFrom\":{\"configMapKeyRef\":{\"name\":\"calico-config\",\"key\":\"veth_mtu\"}}},{\"name\":\"CALICO_IPV4POOL_CIDR\",\"value\":\"10.1.0.0/16\"},{\"name\":\"CALICO_DISABLE_FILE_LOGGING\",\"value\":\"true\"},{\"name\":\"FELIX_DEFAULTENDPOINTTOHOSTACTION\",\"value\":\"ACCEPT\"},{\"name\":\"FELIX_IPV6SUPPORT\",\"value\":\"false\"},{\"name\":\"FELIX_LOGSEVERITYSCREEN\",\"value\":\"error\"},{\"name\":\"FELIX_HEALTHENABLED\",\"value\":\"true\"}]",
"image": "calico/node:v3.13.2",
"image_pull_policy": "IfNotPresent",
"labels": "{\"k8s-app\":\"calico-node\"}",
"liveness_probe": "{\"exec\":{\"command\":[\"/bin/calico-node\",\"-felix-live\"]},\"initialDelaySeconds\":10,\"timeoutSeconds\":1,\"periodSeconds\":10,\"successThreshold\":1,\"failureThreshold\":6}",
"name": "calico-node",
"namespace": "kube-system",
"privileged": "1",
"readiness_probe": "{\"exec\":{\"command\":[\"/bin/calico-node\",\"-felix-ready\"]},\"timeoutSeconds\":1,\"periodSeconds\":10,\"successThreshold\":1,\"failureThreshold\":3}",
"resource_requests": "{\"cpu\":\"250m\"}",
"stdin": "0",
"stdin_once": "0",
"termination_message_path": "/dev/termination-log",
"termination_message_policy": "File",
"tty": "0",
"uid": "7f7da4e6-2c04-5e4e-aedb-bd1e9e8e5469",
"volume_mounts": "[{\"name\":\"lib-modules\",\"readOnly\":true,\"mountPath\":\"/lib/modules\"},{\"name\":\"xtables-lock\",\"mountPath\":\"/run/xtables.lock\"},{\"name\":\"var-run-calico\",\"mountPath\":\"/var/run/calico\"},{\"name\":\"var-lib-calico\",\"mountPath\":\"/var/lib/calico\"},{\"name\":\"policysync\",\"mountPath\":\"/var/run/nodeagent\"}]",
},
}, dss)
}
func TestDaemonSetVolumesGenerate(t *testing.T) {
dss, err := DaemonSetVolumesGenerate(context.TODO(), table.QueryContext{})
assert.Nil(t, err)
assert.Equal(t, []map[string]string{
{
"annotations": "{\"deprecated.daemonset.template.generation\":\"1\"}",
"aws_elastic_block_store_partition": "0",
"cluster_uid": "blah",
"creation_timestamp": "1610476216",
"daemon_set_name": "calico-node",
"gce_persistent_disk_partition": "0",
"host_path_path": "/lib/modules",
"iscsi_discovery_chap_auth": "0",
"iscsi_lun": "0",
"iscsi_session_chap_auth": "0",
"labels": "{\"k8s-app\":\"calico-node\"}",
"name": "lib-modules",
"namespace": "kube-system",
"scale_iossl_enabled": "0",
"uid": "e6fed7f0-f79a-464f-a3d2-b63247a1f590",
"volume_type": "host_path",
},
{
"annotations": "{\"deprecated.daemonset.template.generation\":\"1\"}",
"aws_elastic_block_store_partition": "0",
"cluster_uid": "blah",
"creation_timestamp": "1610476216",
"daemon_set_name": "calico-node",
"gce_persistent_disk_partition": "0",
"host_path_path": "/var/snap/microk8s/current/var/run/calico",
"iscsi_discovery_chap_auth": "0",
"iscsi_lun": "0",
"iscsi_session_chap_auth": "0",
"labels": "{\"k8s-app\":\"calico-node\"}",
"name": "var-run-calico",
"namespace": "kube-system",
"scale_iossl_enabled": "0",
"uid": "e6fed7f0-f79a-464f-a3d2-b63247a1f590",
"volume_type": "host_path",
},
{
"annotations": "{\"deprecated.daemonset.template.generation\":\"1\"}",
"aws_elastic_block_store_partition": "0",
"cluster_uid": "blah",
"creation_timestamp": "1610476216",
"daemon_set_name": "calico-node",
"gce_persistent_disk_partition": "0",
"host_path_path": "/var/snap/microk8s/current/var/lib/calico",
"iscsi_discovery_chap_auth": "0",
"iscsi_lun": "0",
"iscsi_session_chap_auth": "0",
"labels": "{\"k8s-app\":\"calico-node\"}",
"name": "var-lib-calico",
"namespace": "kube-system",
"scale_iossl_enabled": "0",
"uid": "e6fed7f0-f79a-464f-a3d2-b63247a1f590",
"volume_type": "host_path",
},
{
"annotations": "{\"deprecated.daemonset.template.generation\":\"1\"}",
"aws_elastic_block_store_partition": "0",
"cluster_uid": "blah",
"creation_timestamp": "1610476216",
"daemon_set_name": "calico-node",
"gce_persistent_disk_partition": "0",
"host_path_path": "/run/xtables.lock",
"host_path_type": "FileOrCreate",
"iscsi_discovery_chap_auth": "0",
"iscsi_lun": "0",
"iscsi_session_chap_auth": "0",
"labels": "{\"k8s-app\":\"calico-node\"}",
"name": "xtables-lock",
"namespace": "kube-system",
"scale_iossl_enabled": "0",
"uid": "e6fed7f0-f79a-464f-a3d2-b63247a1f590",
"volume_type": "host_path",
},
{
"annotations": "{\"deprecated.daemonset.template.generation\":\"1\"}",
"aws_elastic_block_store_partition": "0",
"cluster_uid": "blah",
"creation_timestamp": "1610476216",
"daemon_set_name": "calico-node",
"gce_persistent_disk_partition": "0",
"host_path_path": "/var/snap/microk8s/current/opt/cni/bin",
"iscsi_discovery_chap_auth": "0",
"iscsi_lun": "0",
"iscsi_session_chap_auth": "0",
"labels": "{\"k8s-app\":\"calico-node\"}",
"name": "cni-bin-dir",
"namespace": "kube-system",
"scale_iossl_enabled": "0",
"uid": "e6fed7f0-f79a-464f-a3d2-b63247a1f590",
"volume_type": "host_path",
},
{
"annotations": "{\"deprecated.daemonset.template.generation\":\"1\"}",
"aws_elastic_block_store_partition": "0",
"cluster_uid": "blah",
"creation_timestamp": "1610476216",
"daemon_set_name": "calico-node",
"gce_persistent_disk_partition": "0",
"host_path_path": "/var/snap/microk8s/current/args/cni-network",
"iscsi_discovery_chap_auth": "0",
"iscsi_lun": "0",
"iscsi_session_chap_auth": "0",
"labels": "{\"k8s-app\":\"calico-node\"}",
"name": "cni-net-dir",
"namespace": "kube-system",
"scale_iossl_enabled": "0",
"uid": "e6fed7f0-f79a-464f-a3d2-b63247a1f590",
"volume_type": "host_path",
},
{
"annotations": "{\"deprecated.daemonset.template.generation\":\"1\"}",
"aws_elastic_block_store_partition": "0",
"cluster_uid": "blah",
"creation_timestamp": "1610476216",
"daemon_set_name": "calico-node",
"gce_persistent_disk_partition": "0",
"host_path_path": "/var/snap/microk8s/current/var/lib/cni/networks",
"iscsi_discovery_chap_auth": "0",
"iscsi_lun": "0",
"iscsi_session_chap_auth": "0",
"labels": "{\"k8s-app\":\"calico-node\"}",
"name": "host-local-net-dir",
"namespace": "kube-system",
"scale_iossl_enabled": "0",
"uid": "e6fed7f0-f79a-464f-a3d2-b63247a1f590",
"volume_type": "host_path",
},
{
"annotations": "{\"deprecated.daemonset.template.generation\":\"1\"}",
"aws_elastic_block_store_partition": "0",
"cluster_uid": "blah",
"creation_timestamp": "1610476216",
"daemon_set_name": "calico-node",
"gce_persistent_disk_partition": "0",
"host_path_path": "/var/snap/microk8s/current/var/run/nodeagent",
"host_path_type": "DirectoryOrCreate",
"iscsi_discovery_chap_auth": "0",
"iscsi_lun": "0",
"iscsi_session_chap_auth": "0",
"labels": "{\"k8s-app\":\"calico-node\"}",
"name": "policysync",
"namespace": "kube-system",
"scale_iossl_enabled": "0",
"uid": "e6fed7f0-f79a-464f-a3d2-b63247a1f590",
"volume_type": "host_path",
},
{
"annotations": "{\"deprecated.daemonset.template.generation\":\"1\"}",
"aws_elastic_block_store_partition": "0",
"cluster_uid": "blah",
"creation_timestamp": "1610476216",
"daemon_set_name": "calico-node",
"gce_persistent_disk_partition": "0",
"host_path_path": "/usr/libexec/kubernetes/kubelet-plugins/volume/exec/nodeagent~uds",
"host_path_type": "DirectoryOrCreate",
"iscsi_discovery_chap_auth": "0",
"iscsi_lun": "0",
"iscsi_session_chap_auth": "0",
"labels": "{\"k8s-app\":\"calico-node\"}",
"name": "flexvol-driver-host",
"namespace": "kube-system",
"scale_iossl_enabled": "0",
"uid": "e6fed7f0-f79a-464f-a3d2-b63247a1f590",
"volume_type": "host_path",
},
}, dss)
}

View File

@ -0,0 +1,181 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package apps
import (
"context"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/Uptycs/kubequery/internal/k8s"
v1 "k8s.io/api/apps/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type deployment struct {
k8s.CommonNamespacedFields
k8s.CommonPodFields
v1.DeploymentStatus
DeploymentReplicas *int32
Selector *metav1.LabelSelector
Strategy v1.DeploymentStrategy
MinReadySeconds int32
RevisionHistoryLimit *int32
Paused bool
ProgressDeadlineSeconds *int32
}
// DeploymentColumns returns kubernetes deployment fields as Osquery table columns.
func DeploymentColumns() []table.ColumnDefinition {
return k8s.GetSchema(&deployment{})
}
// DeploymentsGenerate generates the kubernetes deployments as Osquery table data.
func DeploymentsGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
options := metav1.ListOptions{}
results := make([]map[string]string, 0)
for {
ds, err := k8s.GetClient().AppsV1().Deployments(metav1.NamespaceAll).List(ctx, options)
if err != nil {
return nil, err
}
for _, d := range ds.Items {
item := &deployment{
CommonNamespacedFields: k8s.GetCommonNamespacedFields(d.ObjectMeta),
CommonPodFields: k8s.GetCommonPodFields(d.Spec.Template.Spec),
DeploymentReplicas: d.Spec.Replicas,
Selector: d.Spec.Selector,
Strategy: d.Spec.Strategy,
MinReadySeconds: d.Spec.MinReadySeconds,
RevisionHistoryLimit: d.Spec.RevisionHistoryLimit,
Paused: d.Spec.Paused,
ProgressDeadlineSeconds: d.Spec.ProgressDeadlineSeconds,
DeploymentStatus: d.Status,
}
results = append(results, k8s.ToMap(item))
}
if ds.Continue == "" {
break
}
options.Continue = ds.Continue
}
return results, nil
}
type deploymentContainer struct {
k8s.CommonNamespacedFields
k8s.CommonContainerFields
DeploymentName string
ContainerType string
}
// DeploymentContainerColumns returns kubernetes deployment container fields as Osquery table columns.
func DeploymentContainerColumns() []table.ColumnDefinition {
return k8s.GetSchema(&deploymentContainer{})
}
// DeploymentContainersGenerate generates the kubernetes deployment containers as Osquery table data.
func DeploymentContainersGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
options := metav1.ListOptions{}
results := make([]map[string]string, 0)
for {
ds, err := k8s.GetClient().AppsV1().Deployments(metav1.NamespaceAll).List(ctx, options)
if err != nil {
return nil, err
}
for _, d := range ds.Items {
for _, c := range d.Spec.Template.Spec.InitContainers {
item := &deploymentContainer{
CommonNamespacedFields: k8s.GetParentCommonNamespacedFields(d.ObjectMeta, c.Name),
CommonContainerFields: k8s.GetCommonContainerFields(c),
DeploymentName: d.Name,
ContainerType: "init",
}
item.Name = c.Name
results = append(results, k8s.ToMap(item))
}
for _, c := range d.Spec.Template.Spec.Containers {
item := &deploymentContainer{
CommonNamespacedFields: k8s.GetParentCommonNamespacedFields(d.ObjectMeta, c.Name),
CommonContainerFields: k8s.GetCommonContainerFields(c),
DeploymentName: d.Name,
ContainerType: "container",
}
item.Name = c.Name
results = append(results, k8s.ToMap(item))
}
for _, c := range d.Spec.Template.Spec.EphemeralContainers {
item := &deploymentContainer{
CommonNamespacedFields: k8s.GetParentCommonNamespacedFields(d.ObjectMeta, c.Name),
CommonContainerFields: k8s.GetCommonEphemeralContainerFields(c),
DeploymentName: d.Name,
ContainerType: "ephemeral",
}
item.Name = c.Name
results = append(results, k8s.ToMap(item))
}
}
if ds.Continue == "" {
break
}
options.Continue = ds.Continue
}
return results, nil
}
type deploymentVolume struct {
k8s.CommonNamespacedFields
k8s.CommonVolumeFields
DeploymentName string
}
// DeploymentVolumeColumns returns kubernetes deployment volume fields as Osquery table columns.
func DeploymentVolumeColumns() []table.ColumnDefinition {
return k8s.GetSchema(&deploymentVolume{})
}
// DeploymentVolumesGenerate generates the kubernetes deployment volumes as Osquery table data.
func DeploymentVolumesGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
options := metav1.ListOptions{}
results := make([]map[string]string, 0)
for {
ds, err := k8s.GetClient().AppsV1().Deployments(metav1.NamespaceAll).List(ctx, options)
if err != nil {
return nil, err
}
for _, d := range ds.Items {
for _, v := range d.Spec.Template.Spec.Volumes {
item := &deploymentVolume{
CommonNamespacedFields: k8s.GetCommonNamespacedFields(d.ObjectMeta),
CommonVolumeFields: k8s.GetCommonVolumeFields(v),
DeploymentName: d.Name,
}
item.Name = v.Name
results = append(results, k8s.ToMap(item))
}
}
if ds.Continue == "" {
break
}
options.Continue = ds.Continue
}
return results, nil
}

View File

@ -0,0 +1,53 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package apps
import (
"context"
"testing"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/stretchr/testify/assert"
)
func TestDeploymentsGenerate(t *testing.T) {
ds, err := DeploymentsGenerate(context.TODO(), table.QueryContext{})
assert.Nil(t, err)
assert.Equal(t, []map[string]string{
{
"available_replicas": "0",
"cluster_uid": "blah",
"creation_timestamp": "0",
"host_ipc": "0",
"host_network": "0",
"host_pid": "0",
"min_ready_seconds": "0",
"observed_generation": "0",
"paused": "0",
"ready_replicas": "0",
"replicas": "0",
"strategy": "{}",
"unavailable_replicas": "0",
"updated_replicas": "0",
},
}, ds)
}
func TestDeploymentContainersGenerate(t *testing.T) {
ds, err := DeploymentContainersGenerate(context.TODO(), table.QueryContext{})
assert.Nil(t, err)
assert.Equal(t, []map[string]string{}, ds)
}
func TestDeploymentVolumesGenerate(t *testing.T) {
ds, err := DeploymentVolumesGenerate(context.TODO(), table.QueryContext{})
assert.Nil(t, err)
assert.Equal(t, []map[string]string{}, ds)
}

View File

@ -0,0 +1,47 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package apps
import (
"encoding/json"
"io/ioutil"
"path/filepath"
"github.com/Uptycs/kubequery/internal/k8s"
v1 "k8s.io/api/apps/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes/fake"
)
func loadTestResource(name string, v interface{}) {
path := filepath.Join("testdata", name)
data, err := ioutil.ReadFile(path)
if err != nil {
panic(err)
}
err = json.Unmarshal(data, v)
if err != nil {
panic(err)
}
}
func init() {
ds := &v1.DaemonSet{}
loadTestResource("daemon_set_test.json", ds)
d := &v1.Deployment{}
loadTestResource("deployment_test.json", d)
rs := &v1.ReplicaSet{}
loadTestResource("replica_set_test.json", rs)
ss := &v1.StatefulSet{}
loadTestResource("stateful_set_test.json", ss)
k8s.SetClient(fake.NewSimpleClientset(ds, d, rs, ss), types.UID("blah"), "")
}

View File

@ -0,0 +1,173 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package apps
import (
"context"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/Uptycs/kubequery/internal/k8s"
v1 "k8s.io/api/apps/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type replicaSet struct {
k8s.CommonNamespacedFields
k8s.CommonPodFields
v1.ReplicaSetStatus
ReplicaSetReplicas *int32
MinReadySeconds int32
Selector *metav1.LabelSelector
}
// ReplicaSetColumns returns kubernetes replica set fields as Osquery table columns.
func ReplicaSetColumns() []table.ColumnDefinition {
return k8s.GetSchema(&replicaSet{})
}
// ReplicaSetsGenerate generates the kubernetes replica sets as Osquery table data.
func ReplicaSetsGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
options := metav1.ListOptions{}
results := make([]map[string]string, 0)
for {
rss, err := k8s.GetClient().AppsV1().ReplicaSets(metav1.NamespaceAll).List(ctx, options)
if err != nil {
return nil, err
}
for _, rs := range rss.Items {
item := &replicaSet{
CommonNamespacedFields: k8s.GetCommonNamespacedFields(rs.ObjectMeta),
CommonPodFields: k8s.GetCommonPodFields(rs.Spec.Template.Spec),
ReplicaSetStatus: rs.Status,
ReplicaSetReplicas: rs.Spec.Replicas,
MinReadySeconds: rs.Spec.MinReadySeconds,
Selector: rs.Spec.Selector,
}
results = append(results, k8s.ToMap(item))
}
if rss.Continue == "" {
break
}
options.Continue = rss.Continue
}
return results, nil
}
type replicaSetContainer struct {
k8s.CommonNamespacedFields
k8s.CommonContainerFields
ReplicaSetName string
ContainerType string
}
// ReplicaSetContainerColumns returns kubernetes replica set container fields as Osquery table columns.
func ReplicaSetContainerColumns() []table.ColumnDefinition {
return k8s.GetSchema(&replicaSetContainer{})
}
// ReplicaSetContainersGenerate generates the kubernetes replica set containers as Osquery table data.
func ReplicaSetContainersGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
options := metav1.ListOptions{}
results := make([]map[string]string, 0)
for {
rss, err := k8s.GetClient().AppsV1().ReplicaSets(metav1.NamespaceAll).List(ctx, options)
if err != nil {
return nil, err
}
for _, rs := range rss.Items {
for _, c := range rs.Spec.Template.Spec.InitContainers {
item := &replicaSetContainer{
CommonNamespacedFields: k8s.GetParentCommonNamespacedFields(rs.ObjectMeta, c.Name),
CommonContainerFields: k8s.GetCommonContainerFields(c),
ReplicaSetName: rs.Name,
ContainerType: "init",
}
item.Name = c.Name
results = append(results, k8s.ToMap(item))
}
for _, c := range rs.Spec.Template.Spec.Containers {
item := &replicaSetContainer{
CommonNamespacedFields: k8s.GetParentCommonNamespacedFields(rs.ObjectMeta, c.Name),
CommonContainerFields: k8s.GetCommonContainerFields(c),
ReplicaSetName: rs.Name,
ContainerType: "container",
}
item.Name = c.Name
results = append(results, k8s.ToMap(item))
}
for _, c := range rs.Spec.Template.Spec.EphemeralContainers {
item := &replicaSetContainer{
CommonNamespacedFields: k8s.GetParentCommonNamespacedFields(rs.ObjectMeta, c.Name),
CommonContainerFields: k8s.GetCommonEphemeralContainerFields(c),
ReplicaSetName: rs.Name,
ContainerType: "ephemeral",
}
item.Name = c.Name
results = append(results, k8s.ToMap(item))
}
}
if rss.Continue == "" {
break
}
options.Continue = rss.Continue
}
return results, nil
}
type replicaSetVolume struct {
k8s.CommonNamespacedFields
k8s.CommonVolumeFields
ReplicaSetName string
}
// ReplicaSetVolumeColumns returns kubernetes replica set volume fields as Osquery table columns.
func ReplicaSetVolumeColumns() []table.ColumnDefinition {
return k8s.GetSchema(&replicaSetVolume{})
}
// ReplicaSetVolumesGenerate generates the kubernetes replica set volumes as Osquery table data.
func ReplicaSetVolumesGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
options := metav1.ListOptions{}
results := make([]map[string]string, 0)
for {
rss, err := k8s.GetClient().AppsV1().ReplicaSets(metav1.NamespaceAll).List(ctx, options)
if err != nil {
return nil, err
}
for _, rs := range rss.Items {
for _, v := range rs.Spec.Template.Spec.Volumes {
item := &replicaSetVolume{
CommonNamespacedFields: k8s.GetCommonNamespacedFields(rs.ObjectMeta),
CommonVolumeFields: k8s.GetCommonVolumeFields(v),
ReplicaSetName: rs.Name,
}
item.Name = v.Name
results = append(results, k8s.ToMap(item))
}
}
if rss.Continue == "" {
break
}
options.Continue = rss.Continue
}
return results, nil
}

View File

@ -0,0 +1,84 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package apps
import (
"context"
"testing"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/stretchr/testify/assert"
)
func TestReplicaSetsGenerate(t *testing.T) {
rss, err := ReplicaSetsGenerate(context.TODO(), table.QueryContext{})
assert.Nil(t, err)
assert.Equal(t, []map[string]string{
{
"annotations": "{\"deployment.kubernetes.io/desired-replicas\":\"1\",\"deployment.kubernetes.io/max-replicas\":\"2\",\"deployment.kubernetes.io/revision\":\"1\"}",
"available_replicas": "1",
"cluster_uid": "blah",
"creation_timestamp": "1611191304",
"dns_policy": "ClusterFirst",
"fully_labeled_replicas": "1",
"host_ipc": "0",
"host_network": "0",
"host_pid": "0",
"labels": "{\"name\":\"jaeger-operator\",\"pod-template-hash\":\"5db4f9d996\"}",
"min_ready_seconds": "0",
"name": "jaeger-operator-5db4f9d996",
"namespace": "default",
"observed_generation": "1",
"ready_replicas": "1",
"replica_set_replicas": "1",
"replicas": "1",
"restart_policy": "Always",
"scheduler_name": "default-scheduler",
"selector": "{\"matchLabels\":{\"name\":\"jaeger-operator\",\"pod-template-hash\":\"5db4f9d996\"}}",
"service_account_name": "jaeger-operator",
"termination_grace_period_seconds": "30",
"uid": "2efeb411-ff99-434b-a5a2-4e06c2b0afaa",
},
}, rss)
}
func TestReplicaSetContainersGenerate(t *testing.T) {
rss, err := ReplicaSetContainersGenerate(context.TODO(), table.QueryContext{})
assert.Nil(t, err)
assert.Equal(t, []map[string]string{
{
"annotations": "{\"deployment.kubernetes.io/desired-replicas\":\"1\",\"deployment.kubernetes.io/max-replicas\":\"2\",\"deployment.kubernetes.io/revision\":\"1\"}",
"args": "[\"start\"]",
"cluster_uid": "blah",
"container_type": "container",
"creation_timestamp": "1611191304",
"env": "[{\"name\":\"WATCH_NAMESPACE\"},{\"name\":\"POD_NAME\",\"valueFrom\":{\"fieldRef\":{\"apiVersion\":\"v1\",\"fieldPath\":\"metadata.name\"}}},{\"name\":\"POD_NAMESPACE\",\"valueFrom\":{\"fieldRef\":{\"apiVersion\":\"v1\",\"fieldPath\":\"metadata.namespace\"}}},{\"name\":\"OPERATOR_NAME\",\"value\":\"jaeger-operator\"}]",
"image": "jaegertracing/jaeger-operator:1.14.0",
"image_pull_policy": "Always",
"labels": "{\"name\":\"jaeger-operator\",\"pod-template-hash\":\"5db4f9d996\"}",
"name": "jaeger-operator",
"namespace": "default",
"ports": "[{\"name\":\"metrics\",\"containerPort\":8383,\"protocol\":\"TCP\"}]",
"replica_set_name": "jaeger-operator-5db4f9d996",
"stdin": "0",
"stdin_once": "0",
"termination_message_path": "/dev/termination-log",
"termination_message_policy": "File",
"tty": "0",
"uid": "a9c84883-3d97-5b99-8b20-9fcd5e626a02",
},
}, rss)
}
func TestReplicaSetVolumesGenerate(t *testing.T) {
rss, err := ReplicaSetVolumesGenerate(context.TODO(), table.QueryContext{})
assert.Nil(t, err)
assert.Equal(t, []map[string]string{}, rss)
}

View File

@ -0,0 +1,182 @@
/**
* Copyright (c) 2020-present, The kubequery authoss
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package apps
import (
"context"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/Uptycs/kubequery/internal/k8s"
v1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type statefulSet struct {
k8s.CommonNamespacedFields
k8s.CommonPodFields
v1.StatefulSetStatus
StatefulSetReplicas *int32
Selector *metav1.LabelSelector
VolumeClaimTemplates []corev1.PersistentVolumeClaim
ServiceName string
PodManagementPolicy v1.PodManagementPolicyType
UpdateStrategy v1.StatefulSetUpdateStrategy
RevisionHistoryLimit *int32
}
// StatefulSetColumns returns kubernetes stateful set fields as Osquery table columns.
func StatefulSetColumns() []table.ColumnDefinition {
return k8s.GetSchema(&statefulSet{})
}
// StatefulSetsGenerate generates the kubernetes stateful sets as Osquery table data.
func StatefulSetsGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
options := metav1.ListOptions{}
results := make([]map[string]string, 0)
for {
sss, err := k8s.GetClient().AppsV1().StatefulSets(metav1.NamespaceAll).List(ctx, options)
if err != nil {
return nil, err
}
for _, ss := range sss.Items {
item := &statefulSet{
CommonNamespacedFields: k8s.GetCommonNamespacedFields(ss.ObjectMeta),
CommonPodFields: k8s.GetCommonPodFields(ss.Spec.Template.Spec),
StatefulSetStatus: ss.Status,
StatefulSetReplicas: ss.Spec.Replicas,
Selector: ss.Spec.Selector,
VolumeClaimTemplates: ss.Spec.VolumeClaimTemplates,
ServiceName: ss.Spec.ServiceName,
PodManagementPolicy: ss.Spec.PodManagementPolicy,
UpdateStrategy: ss.Spec.UpdateStrategy,
RevisionHistoryLimit: ss.Spec.RevisionHistoryLimit,
}
results = append(results, k8s.ToMap(item))
}
if sss.Continue == "" {
break
}
options.Continue = sss.Continue
}
return results, nil
}
type statefulSetContainer struct {
k8s.CommonNamespacedFields
k8s.CommonContainerFields
StatefulSetName string
ContainerType string
}
// StatefulSetContainerColumns returns kubernetes stateful set container fields as Osquery table columns.
func StatefulSetContainerColumns() []table.ColumnDefinition {
return k8s.GetSchema(&statefulSetContainer{})
}
// StatefulSetContainersGenerate generates the kubernetes stateful set containers as Osquery table data.
func StatefulSetContainersGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
options := metav1.ListOptions{}
results := make([]map[string]string, 0)
for {
sss, err := k8s.GetClient().AppsV1().StatefulSets(metav1.NamespaceAll).List(ctx, options)
if err != nil {
return nil, err
}
for _, ss := range sss.Items {
for _, c := range ss.Spec.Template.Spec.InitContainers {
item := &statefulSetContainer{
CommonNamespacedFields: k8s.GetParentCommonNamespacedFields(ss.ObjectMeta, c.Name),
CommonContainerFields: k8s.GetCommonContainerFields(c),
StatefulSetName: ss.Name,
ContainerType: "init",
}
item.Name = c.Name
results = append(results, k8s.ToMap(item))
}
for _, c := range ss.Spec.Template.Spec.Containers {
item := &statefulSetContainer{
CommonNamespacedFields: k8s.GetParentCommonNamespacedFields(ss.ObjectMeta, c.Name),
CommonContainerFields: k8s.GetCommonContainerFields(c),
StatefulSetName: ss.Name,
ContainerType: "container",
}
item.Name = c.Name
results = append(results, k8s.ToMap(item))
}
for _, c := range ss.Spec.Template.Spec.EphemeralContainers {
item := &statefulSetContainer{
CommonNamespacedFields: k8s.GetParentCommonNamespacedFields(ss.ObjectMeta, c.Name),
CommonContainerFields: k8s.GetCommonEphemeralContainerFields(c),
StatefulSetName: ss.Name,
ContainerType: "ephemeral",
}
item.Name = c.Name
results = append(results, k8s.ToMap(item))
}
}
if sss.Continue == "" {
break
}
options.Continue = sss.Continue
}
return results, nil
}
type statefulSetVolume struct {
k8s.CommonNamespacedFields
k8s.CommonVolumeFields
StatefulSetName string
}
// StatefulSetVolumeColumns returns kubernetes stateful set volume fields as Osquery table columns.
func StatefulSetVolumeColumns() []table.ColumnDefinition {
return k8s.GetSchema(&statefulSetVolume{})
}
// StatefulSetVolumesGenerate generates the kubernetes stateful set volumes as Osquery table data.
func StatefulSetVolumesGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
options := metav1.ListOptions{}
results := make([]map[string]string, 0)
for {
sss, err := k8s.GetClient().AppsV1().StatefulSets(metav1.NamespaceAll).List(ctx, options)
if err != nil {
return nil, err
}
for _, ss := range sss.Items {
for _, v := range ss.Spec.Template.Spec.Volumes {
item := &statefulSetVolume{
CommonNamespacedFields: k8s.GetCommonNamespacedFields(ss.ObjectMeta),
CommonVolumeFields: k8s.GetCommonVolumeFields(v),
StatefulSetName: ss.Name,
}
item.Name = v.Name
results = append(results, k8s.ToMap(item))
}
}
if sss.Continue == "" {
break
}
options.Continue = sss.Continue
}
return results, nil
}

View File

@ -0,0 +1,153 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package apps
import (
"context"
"testing"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/stretchr/testify/assert"
)
func TestStatefulSetsGenerate(t *testing.T) {
sss, err := StatefulSetsGenerate(context.TODO(), table.QueryContext{})
assert.Nil(t, err)
assert.Equal(t, []map[string]string{
{
"available_replicas": "0",
"cluster_uid": "blah",
"collision_count": "0",
"creation_timestamp": "1611191592",
"current_replicas": "1",
"current_revision": "alertmanager-main-6674894c9d",
"dns_policy": "ClusterFirst",
"fs_group": "2000",
"host_ipc": "0",
"host_network": "0",
"host_pid": "0",
"labels": "{\"alertmanager\":\"main\"}",
"name": "alertmanager-main",
"namespace": "monitoring",
"node_selector": "{\"kubernetes.io/os\":\"linux\"}",
"observed_generation": "1",
"pod_management_policy": "Parallel",
"ready_replicas": "1",
"replicas": "1",
"restart_policy": "Always",
"revision_history_limit": "10",
"run_as_non_root": "1",
"run_as_user": "1000",
"scheduler_name": "default-scheduler",
"selector": "{\"matchLabels\":{\"alertmanager\":\"main\",\"app\":\"alertmanager\"}}",
"service_account_name": "alertmanager-main",
"service_name": "alertmanager-operated",
"stateful_set_replicas": "1",
"termination_grace_period_seconds": "120",
"uid": "3c488e7e-420c-4515-b377-5dc3ee082744",
"update_revision": "alertmanager-main-6674894c9d",
"update_strategy": "{\"type\":\"RollingUpdate\"}",
"updated_replicas": "1",
},
}, sss)
}
func TestStatefulSetContainersGenerate(t *testing.T) {
sss, err := StatefulSetContainersGenerate(context.TODO(), table.QueryContext{})
assert.Nil(t, err)
assert.Equal(t, []map[string]string{
{
"args": "[\"--config.file=/etc/alertmanager/config/alertmanager.yaml\",\"--storage.path=/alertmanager\",\"--data.retention=120h\",\"--cluster.listen-address=\",\"--web.listen-address=:9093\",\"--web.route-prefix=/\",\"--cluster.peer=alertmanager-main-0.alertmanager-operated:9094\"]",
"cluster_uid": "blah",
"container_type": "container",
"creation_timestamp": "1611191592",
"env": "[{\"name\":\"POD_IP\",\"valueFrom\":{\"fieldRef\":{\"apiVersion\":\"v1\",\"fieldPath\":\"status.podIP\"}}}]",
"image": "quay.io/prometheus/alertmanager:v0.21.0",
"image_pull_policy": "IfNotPresent",
"labels": "{\"alertmanager\":\"main\"}",
"liveness_probe": "{\"httpGet\":{\"path\":\"/-/healthy\",\"port\":\"web\",\"scheme\":\"HTTP\"},\"timeoutSeconds\":3,\"periodSeconds\":10,\"successThreshold\":1,\"failureThreshold\":10}",
"name": "alertmanager",
"namespace": "monitoring",
"ports": "[{\"name\":\"web\",\"containerPort\":9093,\"protocol\":\"TCP\"},{\"name\":\"mesh-tcp\",\"containerPort\":9094,\"protocol\":\"TCP\"},{\"name\":\"mesh-udp\",\"containerPort\":9094,\"protocol\":\"UDP\"}]",
"readiness_probe": "{\"httpGet\":{\"path\":\"/-/ready\",\"port\":\"web\",\"scheme\":\"HTTP\"},\"initialDelaySeconds\":3,\"timeoutSeconds\":3,\"periodSeconds\":5,\"successThreshold\":1,\"failureThreshold\":10}",
"resource_requests": "{\"memory\":\"200Mi\"}",
"stateful_set_name": "alertmanager-main",
"stdin": "0",
"stdin_once": "0",
"termination_message_path": "/dev/termination-log",
"termination_message_policy": "FallbackToLogsOnError",
"tty": "0",
"uid": "da9bb224-1bf1-5960-a83c-b77a73ea6e79",
"volume_mounts": "[{\"name\":\"config-volume\",\"mountPath\":\"/etc/alertmanager/config\"},{\"name\":\"alertmanager-main-db\",\"mountPath\":\"/alertmanager\"}]",
},
{
"args": "[\"-webhook-url=http://localhost:9093/-/reload\",\"-volume-dir=/etc/alertmanager/config\"]",
"cluster_uid": "blah",
"container_type": "container",
"creation_timestamp": "1611191592",
"image": "jimmidyson/configmap-reload:v0.3.0",
"image_pull_policy": "IfNotPresent",
"labels": "{\"alertmanager\":\"main\"}",
"name": "config-reloader",
"namespace": "monitoring",
"resource_limits": "{\"cpu\":\"100m\",\"memory\":\"25Mi\"}",
"stateful_set_name": "alertmanager-main",
"stdin": "0",
"stdin_once": "0",
"termination_message_path": "/dev/termination-log",
"termination_message_policy": "FallbackToLogsOnError",
"tty": "0",
"uid": "69afdc5a-a3de-59b5-8151-4103b933f2cf",
"volume_mounts": "[{\"name\":\"config-volume\",\"readOnly\":true,\"mountPath\":\"/etc/alertmanager/config\"}]",
},
}, sss)
}
func TestStatefulSetVolumesGenerate(t *testing.T) {
sss, err := StatefulSetVolumesGenerate(context.TODO(), table.QueryContext{})
assert.Nil(t, err)
assert.Equal(t, []map[string]string{
{
"aws_elastic_block_store_partition": "0",
"cluster_uid": "blah",
"creation_timestamp": "1611191592",
"gce_persistent_disk_partition": "0",
"iscsi_discovery_chap_auth": "0",
"iscsi_lun": "0",
"iscsi_session_chap_auth": "0",
"labels": "{\"alertmanager\":\"main\"}",
"name": "config-volume",
"namespace": "monitoring",
"scale_iossl_enabled": "0",
"secret_default_mode": "420",
"secret_name": "alertmanager-main",
"stateful_set_name": "alertmanager-main",
"uid": "3c488e7e-420c-4515-b377-5dc3ee082744",
"volume_type": "secret",
},
{
"aws_elastic_block_store_partition": "0",
"cluster_uid": "blah",
"creation_timestamp": "1611191592",
"empty_dir_size_limit": "<nil>",
"gce_persistent_disk_partition": "0",
"iscsi_discovery_chap_auth": "0",
"iscsi_lun": "0",
"iscsi_session_chap_auth": "0",
"labels": "{\"alertmanager\":\"main\"}",
"name": "alertmanager-main-db",
"namespace": "monitoring",
"scale_iossl_enabled": "0",
"stateful_set_name": "alertmanager-main",
"uid": "3c488e7e-420c-4515-b377-5dc3ee082744",
"volume_type": "empty_dir",
},
}, sss)
}

View File

@ -0,0 +1,910 @@
{
"apiVersion": "apps/v1",
"kind": "DaemonSet",
"metadata": {
"annotations": {
"deprecated.daemonset.template.generation": "1"
},
"creationTimestamp": "2021-01-12T18:30:16Z",
"generation": 1,
"labels": {
"k8s-app": "calico-node"
},
"managedFields": [
{
"apiVersion": "apps/v1",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:metadata": {
"f:annotations": {
".": {},
"f:deprecated.daemonset.template.generation": {},
"f:kubectl.kubernetes.io/last-applied-configuration": {}
},
"f:labels": {
".": {},
"f:k8s-app": {}
}
},
"f:spec": {
"f:revisionHistoryLimit": {},
"f:selector": {},
"f:template": {
"f:metadata": {
"f:annotations": {
".": {},
"f:scheduler.alpha.kubernetes.io/critical-pod": {}
},
"f:labels": {
".": {},
"f:k8s-app": {}
}
},
"f:spec": {
"f:containers": {
"k:{\"name\":\"calico-node\"}": {
".": {},
"f:env": {
".": {},
"k:{\"name\":\"CALICO_DISABLE_FILE_LOGGING\"}": {
".": {},
"f:name": {},
"f:value": {}
},
"k:{\"name\":\"CALICO_IPV4POOL_CIDR\"}": {
".": {},
"f:name": {},
"f:value": {}
},
"k:{\"name\":\"CALICO_IPV4POOL_VXLAN\"}": {
".": {},
"f:name": {},
"f:value": {}
},
"k:{\"name\":\"CALICO_NETWORKING_BACKEND\"}": {
".": {},
"f:name": {},
"f:valueFrom": {
".": {},
"f:configMapKeyRef": {
".": {},
"f:key": {},
"f:name": {}
}
}
},
"k:{\"name\":\"CLUSTER_TYPE\"}": {
".": {},
"f:name": {},
"f:value": {}
},
"k:{\"name\":\"DATASTORE_TYPE\"}": {
".": {},
"f:name": {},
"f:value": {}
},
"k:{\"name\":\"FELIX_DEFAULTENDPOINTTOHOSTACTION\"}": {
".": {},
"f:name": {},
"f:value": {}
},
"k:{\"name\":\"FELIX_HEALTHENABLED\"}": {
".": {},
"f:name": {},
"f:value": {}
},
"k:{\"name\":\"FELIX_IPINIPMTU\"}": {
".": {},
"f:name": {},
"f:valueFrom": {
".": {},
"f:configMapKeyRef": {
".": {},
"f:key": {},
"f:name": {}
}
}
},
"k:{\"name\":\"FELIX_IPV6SUPPORT\"}": {
".": {},
"f:name": {},
"f:value": {}
},
"k:{\"name\":\"FELIX_LOGSEVERITYSCREEN\"}": {
".": {},
"f:name": {},
"f:value": {}
},
"k:{\"name\":\"IP\"}": {
".": {},
"f:name": {},
"f:value": {}
},
"k:{\"name\":\"IP_AUTODETECTION_METHOD\"}": {
".": {},
"f:name": {},
"f:value": {}
},
"k:{\"name\":\"NODENAME\"}": {
".": {},
"f:name": {},
"f:valueFrom": {
".": {},
"f:fieldRef": {
".": {},
"f:apiVersion": {},
"f:fieldPath": {}
}
}
},
"k:{\"name\":\"WAIT_FOR_DATASTORE\"}": {
".": {},
"f:name": {},
"f:value": {}
}
},
"f:image": {},
"f:imagePullPolicy": {},
"f:livenessProbe": {
".": {},
"f:exec": {
".": {},
"f:command": {}
},
"f:failureThreshold": {},
"f:initialDelaySeconds": {},
"f:periodSeconds": {},
"f:successThreshold": {},
"f:timeoutSeconds": {}
},
"f:name": {},
"f:readinessProbe": {
".": {},
"f:exec": {
".": {},
"f:command": {}
},
"f:failureThreshold": {},
"f:periodSeconds": {},
"f:successThreshold": {},
"f:timeoutSeconds": {}
},
"f:resources": {
".": {},
"f:requests": {
".": {},
"f:cpu": {}
}
},
"f:securityContext": {
".": {},
"f:privileged": {}
},
"f:terminationMessagePath": {},
"f:terminationMessagePolicy": {},
"f:volumeMounts": {
".": {},
"k:{\"mountPath\":\"/lib/modules\"}": {
".": {},
"f:mountPath": {},
"f:name": {},
"f:readOnly": {}
},
"k:{\"mountPath\":\"/run/xtables.lock\"}": {
".": {},
"f:mountPath": {},
"f:name": {}
},
"k:{\"mountPath\":\"/var/lib/calico\"}": {
".": {},
"f:mountPath": {},
"f:name": {}
},
"k:{\"mountPath\":\"/var/run/calico\"}": {
".": {},
"f:mountPath": {},
"f:name": {}
},
"k:{\"mountPath\":\"/var/run/nodeagent\"}": {
".": {},
"f:mountPath": {},
"f:name": {}
}
}
}
},
"f:dnsPolicy": {},
"f:hostNetwork": {},
"f:initContainers": {
".": {},
"k:{\"name\":\"flexvol-driver\"}": {
".": {},
"f:image": {},
"f:imagePullPolicy": {},
"f:name": {},
"f:resources": {},
"f:securityContext": {
".": {},
"f:privileged": {}
},
"f:terminationMessagePath": {},
"f:terminationMessagePolicy": {},
"f:volumeMounts": {
".": {},
"k:{\"mountPath\":\"/host/driver\"}": {
".": {},
"f:mountPath": {},
"f:name": {}
}
}
},
"k:{\"name\":\"install-cni\"}": {
".": {},
"f:command": {},
"f:env": {
".": {},
"k:{\"name\":\"CNI_CONF_NAME\"}": {
".": {},
"f:name": {},
"f:value": {}
},
"k:{\"name\":\"CNI_MTU\"}": {
".": {},
"f:name": {},
"f:valueFrom": {
".": {},
"f:configMapKeyRef": {
".": {},
"f:key": {},
"f:name": {}
}
}
},
"k:{\"name\":\"CNI_NETWORK_CONFIG\"}": {
".": {},
"f:name": {},
"f:valueFrom": {
".": {},
"f:configMapKeyRef": {
".": {},
"f:key": {},
"f:name": {}
}
}
},
"k:{\"name\":\"CNI_NET_DIR\"}": {
".": {},
"f:name": {},
"f:value": {}
},
"k:{\"name\":\"KUBERNETES_NODE_NAME\"}": {
".": {},
"f:name": {},
"f:valueFrom": {
".": {},
"f:fieldRef": {
".": {},
"f:apiVersion": {},
"f:fieldPath": {}
}
}
},
"k:{\"name\":\"SLEEP\"}": {
".": {},
"f:name": {},
"f:value": {}
}
},
"f:image": {},
"f:imagePullPolicy": {},
"f:name": {},
"f:resources": {},
"f:securityContext": {
".": {},
"f:privileged": {}
},
"f:terminationMessagePath": {},
"f:terminationMessagePolicy": {},
"f:volumeMounts": {
".": {},
"k:{\"mountPath\":\"/host/etc/cni/net.d\"}": {
".": {},
"f:mountPath": {},
"f:name": {}
},
"k:{\"mountPath\":\"/host/opt/cni/bin\"}": {
".": {},
"f:mountPath": {},
"f:name": {}
}
}
},
"k:{\"name\":\"upgrade-ipam\"}": {
".": {},
"f:command": {},
"f:env": {
".": {},
"k:{\"name\":\"CALICO_NETWORKING_BACKEND\"}": {
".": {},
"f:name": {},
"f:valueFrom": {
".": {},
"f:configMapKeyRef": {
".": {},
"f:key": {},
"f:name": {}
}
}
},
"k:{\"name\":\"KUBERNETES_NODE_NAME\"}": {
".": {},
"f:name": {},
"f:valueFrom": {
".": {},
"f:fieldRef": {
".": {},
"f:apiVersion": {},
"f:fieldPath": {}
}
}
}
},
"f:image": {},
"f:imagePullPolicy": {},
"f:name": {},
"f:resources": {},
"f:securityContext": {
".": {},
"f:privileged": {}
},
"f:terminationMessagePath": {},
"f:terminationMessagePolicy": {},
"f:volumeMounts": {
".": {},
"k:{\"mountPath\":\"/host/opt/cni/bin\"}": {
".": {},
"f:mountPath": {},
"f:name": {}
},
"k:{\"mountPath\":\"/var/lib/cni/networks\"}": {
".": {},
"f:mountPath": {},
"f:name": {}
}
}
}
},
"f:nodeSelector": {
".": {},
"f:kubernetes.io/os": {}
},
"f:priorityClassName": {},
"f:restartPolicy": {},
"f:schedulerName": {},
"f:securityContext": {},
"f:serviceAccount": {},
"f:serviceAccountName": {},
"f:terminationGracePeriodSeconds": {},
"f:tolerations": {},
"f:volumes": {
".": {},
"k:{\"name\":\"cni-bin-dir\"}": {
".": {},
"f:hostPath": {
".": {},
"f:path": {},
"f:type": {}
},
"f:name": {}
},
"k:{\"name\":\"cni-net-dir\"}": {
".": {},
"f:hostPath": {
".": {},
"f:path": {},
"f:type": {}
},
"f:name": {}
},
"k:{\"name\":\"flexvol-driver-host\"}": {
".": {},
"f:hostPath": {
".": {},
"f:path": {},
"f:type": {}
},
"f:name": {}
},
"k:{\"name\":\"host-local-net-dir\"}": {
".": {},
"f:hostPath": {
".": {},
"f:path": {},
"f:type": {}
},
"f:name": {}
},
"k:{\"name\":\"lib-modules\"}": {
".": {},
"f:hostPath": {
".": {},
"f:path": {},
"f:type": {}
},
"f:name": {}
},
"k:{\"name\":\"policysync\"}": {
".": {},
"f:hostPath": {
".": {},
"f:path": {},
"f:type": {}
},
"f:name": {}
},
"k:{\"name\":\"var-lib-calico\"}": {
".": {},
"f:hostPath": {
".": {},
"f:path": {},
"f:type": {}
},
"f:name": {}
},
"k:{\"name\":\"var-run-calico\"}": {
".": {},
"f:hostPath": {
".": {},
"f:path": {},
"f:type": {}
},
"f:name": {}
},
"k:{\"name\":\"xtables-lock\"}": {
".": {},
"f:hostPath": {
".": {},
"f:path": {},
"f:type": {}
},
"f:name": {}
}
}
}
},
"f:updateStrategy": {
"f:rollingUpdate": {
".": {},
"f:maxUnavailable": {}
},
"f:type": {}
}
}
},
"manager": "kubectl-client-side-apply",
"operation": "Update",
"time": "2021-01-12T18:30:16Z"
},
{
"apiVersion": "apps/v1",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:status": {
"f:currentNumberScheduled": {},
"f:desiredNumberScheduled": {},
"f:numberAvailable": {},
"f:numberReady": {},
"f:observedGeneration": {},
"f:updatedNumberScheduled": {}
}
},
"manager": "kube-controller-manager",
"operation": "Update",
"time": "2021-01-21T01:05:37Z"
}
],
"name": "calico-node",
"namespace": "kube-system",
"resourceVersion": "450274",
"selfLink": "/apis/apps/v1/namespaces/kube-system/daemonsets/calico-node",
"uid": "e6fed7f0-f79a-464f-a3d2-b63247a1f590"
},
"spec": {
"revisionHistoryLimit": 10,
"selector": {
"matchLabels": {
"k8s-app": "calico-node"
}
},
"template": {
"metadata": {
"annotations": {
"scheduler.alpha.kubernetes.io/critical-pod": ""
},
"creationTimestamp": null,
"labels": {
"k8s-app": "calico-node"
}
},
"spec": {
"containers": [
{
"env": [
{
"name": "DATASTORE_TYPE",
"value": "kubernetes"
},
{
"name": "WAIT_FOR_DATASTORE",
"value": "true"
},
{
"name": "NODENAME",
"valueFrom": {
"fieldRef": {
"apiVersion": "v1",
"fieldPath": "spec.nodeName"
}
}
},
{
"name": "CALICO_NETWORKING_BACKEND",
"valueFrom": {
"configMapKeyRef": {
"key": "calico_backend",
"name": "calico-config"
}
}
},
{
"name": "CLUSTER_TYPE",
"value": "k8s,bgp"
},
{
"name": "IP",
"value": "autodetect"
},
{
"name": "IP_AUTODETECTION_METHOD",
"value": "first-found"
},
{
"name": "CALICO_IPV4POOL_VXLAN",
"value": "Always"
},
{
"name": "FELIX_IPINIPMTU",
"valueFrom": {
"configMapKeyRef": {
"key": "veth_mtu",
"name": "calico-config"
}
}
},
{
"name": "CALICO_IPV4POOL_CIDR",
"value": "10.1.0.0/16"
},
{
"name": "CALICO_DISABLE_FILE_LOGGING",
"value": "true"
},
{
"name": "FELIX_DEFAULTENDPOINTTOHOSTACTION",
"value": "ACCEPT"
},
{
"name": "FELIX_IPV6SUPPORT",
"value": "false"
},
{
"name": "FELIX_LOGSEVERITYSCREEN",
"value": "error"
},
{
"name": "FELIX_HEALTHENABLED",
"value": "true"
}
],
"image": "calico/node:v3.13.2",
"imagePullPolicy": "IfNotPresent",
"livenessProbe": {
"exec": {
"command": [
"/bin/calico-node",
"-felix-live"
]
},
"failureThreshold": 6,
"initialDelaySeconds": 10,
"periodSeconds": 10,
"successThreshold": 1,
"timeoutSeconds": 1
},
"name": "calico-node",
"readinessProbe": {
"exec": {
"command": [
"/bin/calico-node",
"-felix-ready"
]
},
"failureThreshold": 3,
"periodSeconds": 10,
"successThreshold": 1,
"timeoutSeconds": 1
},
"resources": {
"requests": {
"cpu": "250m"
}
},
"securityContext": {
"privileged": true
},
"terminationMessagePath": "/dev/termination-log",
"terminationMessagePolicy": "File",
"volumeMounts": [
{
"mountPath": "/lib/modules",
"name": "lib-modules",
"readOnly": true
},
{
"mountPath": "/run/xtables.lock",
"name": "xtables-lock"
},
{
"mountPath": "/var/run/calico",
"name": "var-run-calico"
},
{
"mountPath": "/var/lib/calico",
"name": "var-lib-calico"
},
{
"mountPath": "/var/run/nodeagent",
"name": "policysync"
}
]
}
],
"dnsPolicy": "ClusterFirst",
"hostNetwork": true,
"initContainers": [
{
"command": [
"/opt/cni/bin/calico-ipam",
"-upgrade"
],
"env": [
{
"name": "KUBERNETES_NODE_NAME",
"valueFrom": {
"fieldRef": {
"apiVersion": "v1",
"fieldPath": "spec.nodeName"
}
}
},
{
"name": "CALICO_NETWORKING_BACKEND",
"valueFrom": {
"configMapKeyRef": {
"key": "calico_backend",
"name": "calico-config"
}
}
}
],
"image": "calico/cni:v3.13.2",
"imagePullPolicy": "IfNotPresent",
"name": "upgrade-ipam",
"resources": {},
"securityContext": {
"privileged": true
},
"terminationMessagePath": "/dev/termination-log",
"terminationMessagePolicy": "File",
"volumeMounts": [
{
"mountPath": "/var/lib/cni/networks",
"name": "host-local-net-dir"
},
{
"mountPath": "/host/opt/cni/bin",
"name": "cni-bin-dir"
}
]
},
{
"command": [
"/install-cni.sh"
],
"env": [
{
"name": "CNI_CONF_NAME",
"value": "10-calico.conflist"
},
{
"name": "CNI_NETWORK_CONFIG",
"valueFrom": {
"configMapKeyRef": {
"key": "cni_network_config",
"name": "calico-config"
}
}
},
{
"name": "KUBERNETES_NODE_NAME",
"valueFrom": {
"fieldRef": {
"apiVersion": "v1",
"fieldPath": "spec.nodeName"
}
}
},
{
"name": "CNI_MTU",
"valueFrom": {
"configMapKeyRef": {
"key": "veth_mtu",
"name": "calico-config"
}
}
},
{
"name": "SLEEP",
"value": "false"
},
{
"name": "CNI_NET_DIR",
"value": "/var/snap/microk8s/current/args/cni-network"
}
],
"image": "calico/cni:v3.13.2",
"imagePullPolicy": "IfNotPresent",
"name": "install-cni",
"resources": {},
"securityContext": {
"privileged": true
},
"terminationMessagePath": "/dev/termination-log",
"terminationMessagePolicy": "File",
"volumeMounts": [
{
"mountPath": "/host/opt/cni/bin",
"name": "cni-bin-dir"
},
{
"mountPath": "/host/etc/cni/net.d",
"name": "cni-net-dir"
}
]
},
{
"image": "calico/pod2daemon-flexvol:v3.13.2",
"imagePullPolicy": "IfNotPresent",
"name": "flexvol-driver",
"resources": {},
"securityContext": {
"privileged": true
},
"terminationMessagePath": "/dev/termination-log",
"terminationMessagePolicy": "File",
"volumeMounts": [
{
"mountPath": "/host/driver",
"name": "flexvol-driver-host"
}
]
}
],
"nodeSelector": {
"kubernetes.io/os": "linux"
},
"priorityClassName": "system-node-critical",
"restartPolicy": "Always",
"schedulerName": "default-scheduler",
"securityContext": {},
"serviceAccount": "calico-node",
"serviceAccountName": "calico-node",
"terminationGracePeriodSeconds": 0,
"tolerations": [
{
"effect": "NoSchedule",
"operator": "Exists"
},
{
"key": "CriticalAddonsOnly",
"operator": "Exists"
},
{
"effect": "NoExecute",
"operator": "Exists"
}
],
"volumes": [
{
"hostPath": {
"path": "/lib/modules",
"type": ""
},
"name": "lib-modules"
},
{
"hostPath": {
"path": "/var/snap/microk8s/current/var/run/calico",
"type": ""
},
"name": "var-run-calico"
},
{
"hostPath": {
"path": "/var/snap/microk8s/current/var/lib/calico",
"type": ""
},
"name": "var-lib-calico"
},
{
"hostPath": {
"path": "/run/xtables.lock",
"type": "FileOrCreate"
},
"name": "xtables-lock"
},
{
"hostPath": {
"path": "/var/snap/microk8s/current/opt/cni/bin",
"type": ""
},
"name": "cni-bin-dir"
},
{
"hostPath": {
"path": "/var/snap/microk8s/current/args/cni-network",
"type": ""
},
"name": "cni-net-dir"
},
{
"hostPath": {
"path": "/var/snap/microk8s/current/var/lib/cni/networks",
"type": ""
},
"name": "host-local-net-dir"
},
{
"hostPath": {
"path": "/var/snap/microk8s/current/var/run/nodeagent",
"type": "DirectoryOrCreate"
},
"name": "policysync"
},
{
"hostPath": {
"path": "/usr/libexec/kubernetes/kubelet-plugins/volume/exec/nodeagent~uds",
"type": "DirectoryOrCreate"
},
"name": "flexvol-driver-host"
}
]
}
},
"updateStrategy": {
"rollingUpdate": {
"maxUnavailable": 1
},
"type": "RollingUpdate"
}
},
"status": {
"currentNumberScheduled": 1,
"desiredNumberScheduled": 1,
"numberAvailable": 1,
"numberMisscheduled": 0,
"numberReady": 1,
"observedGeneration": 1,
"updatedNumberScheduled": 1
}
}

View File

@ -0,0 +1,739 @@
{
"apiVersion": "v1",
"items": [
{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": {
"annotations": {
"deployment.kubernetes.io/revision": "1",
"kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"apps/v1\",\"kind\":\"Deployment\",\"metadata\":{\"annotations\":{},\"name\":\"jaeger-operator\",\"namespace\":\"default\"},\"spec\":{\"replicas\":1,\"selector\":{\"matchLabels\":{\"name\":\"jaeger-operator\"}},\"template\":{\"metadata\":{\"labels\":{\"name\":\"jaeger-operator\"}},\"spec\":{\"containers\":[{\"args\":[\"start\"],\"env\":[{\"name\":\"WATCH_NAMESPACE\",\"value\":\"\"},{\"name\":\"POD_NAME\",\"valueFrom\":{\"fieldRef\":{\"fieldPath\":\"metadata.name\"}}},{\"name\":\"POD_NAMESPACE\",\"valueFrom\":{\"fieldRef\":{\"fieldPath\":\"metadata.namespace\"}}},{\"name\":\"OPERATOR_NAME\",\"value\":\"jaeger-operator\"}],\"image\":\"jaegertracing/jaeger-operator:1.14.0\",\"imagePullPolicy\":\"Always\",\"name\":\"jaeger-operator\",\"ports\":[{\"containerPort\":8383,\"name\":\"metrics\"}]}],\"serviceAccountName\":\"jaeger-operator\"}}}}\n"
},
"creationTimestamp": "2021-01-21T01:08:24Z",
"generation": 1,
"managedFields": [
{
"apiVersion": "apps/v1",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:metadata": {
"f:annotations": {
".": {},
"f:kubectl.kubernetes.io/last-applied-configuration": {}
}
},
"f:spec": {
"f:progressDeadlineSeconds": {},
"f:replicas": {},
"f:revisionHistoryLimit": {},
"f:selector": {},
"f:strategy": {
"f:rollingUpdate": {
".": {},
"f:maxSurge": {},
"f:maxUnavailable": {}
},
"f:type": {}
},
"f:template": {
"f:metadata": {
"f:labels": {
".": {},
"f:name": {}
}
},
"f:spec": {
"f:containers": {
"k:{\"name\":\"jaeger-operator\"}": {
".": {},
"f:args": {},
"f:env": {
".": {},
"k:{\"name\":\"OPERATOR_NAME\"}": {
".": {},
"f:name": {},
"f:value": {}
},
"k:{\"name\":\"POD_NAME\"}": {
".": {},
"f:name": {},
"f:valueFrom": {
".": {},
"f:fieldRef": {
".": {},
"f:apiVersion": {},
"f:fieldPath": {}
}
}
},
"k:{\"name\":\"POD_NAMESPACE\"}": {
".": {},
"f:name": {},
"f:valueFrom": {
".": {},
"f:fieldRef": {
".": {},
"f:apiVersion": {},
"f:fieldPath": {}
}
}
},
"k:{\"name\":\"WATCH_NAMESPACE\"}": {
".": {},
"f:name": {}
}
},
"f:image": {},
"f:imagePullPolicy": {},
"f:name": {},
"f:ports": {
".": {},
"k:{\"containerPort\":8383,\"protocol\":\"TCP\"}": {
".": {},
"f:containerPort": {},
"f:name": {},
"f:protocol": {}
}
},
"f:resources": {},
"f:terminationMessagePath": {},
"f:terminationMessagePolicy": {}
}
},
"f:dnsPolicy": {},
"f:restartPolicy": {},
"f:schedulerName": {},
"f:securityContext": {},
"f:serviceAccount": {},
"f:serviceAccountName": {},
"f:terminationGracePeriodSeconds": {}
}
}
}
},
"manager": "kubectl-client-side-apply",
"operation": "Update",
"time": "2021-01-21T01:08:24Z"
},
{
"apiVersion": "apps/v1",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:metadata": {
"f:annotations": {
"f:deployment.kubernetes.io/revision": {}
}
},
"f:status": {
"f:availableReplicas": {},
"f:conditions": {
".": {},
"k:{\"type\":\"Available\"}": {
".": {},
"f:lastTransitionTime": {},
"f:lastUpdateTime": {},
"f:message": {},
"f:reason": {},
"f:status": {},
"f:type": {}
},
"k:{\"type\":\"Progressing\"}": {
".": {},
"f:lastTransitionTime": {},
"f:lastUpdateTime": {},
"f:message": {},
"f:reason": {},
"f:status": {},
"f:type": {}
}
},
"f:observedGeneration": {},
"f:readyReplicas": {},
"f:replicas": {},
"f:updatedReplicas": {}
}
},
"manager": "kube-controller-manager",
"operation": "Update",
"time": "2021-01-21T01:08:52Z"
}
],
"name": "jaeger-operator",
"namespace": "default",
"resourceVersion": "451812",
"selfLink": "/apis/apps/v1/namespaces/default/deployments/jaeger-operator",
"uid": "baa856ea-2d04-4bbb-b9be-aa5b89c58087"
},
"spec": {
"progressDeadlineSeconds": 600,
"replicas": 1,
"revisionHistoryLimit": 10,
"selector": {
"matchLabels": {
"name": "jaeger-operator"
}
},
"strategy": {
"rollingUpdate": {
"maxSurge": "25%",
"maxUnavailable": "25%"
},
"type": "RollingUpdate"
},
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"name": "jaeger-operator"
}
},
"spec": {
"containers": [
{
"args": [
"start"
],
"env": [
{
"name": "WATCH_NAMESPACE"
},
{
"name": "POD_NAME",
"valueFrom": {
"fieldRef": {
"apiVersion": "v1",
"fieldPath": "metadata.name"
}
}
},
{
"name": "POD_NAMESPACE",
"valueFrom": {
"fieldRef": {
"apiVersion": "v1",
"fieldPath": "metadata.namespace"
}
}
},
{
"name": "OPERATOR_NAME",
"value": "jaeger-operator"
}
],
"image": "jaegertracing/jaeger-operator:1.14.0",
"imagePullPolicy": "Always",
"name": "jaeger-operator",
"ports": [
{
"containerPort": 8383,
"name": "metrics",
"protocol": "TCP"
}
],
"resources": {},
"terminationMessagePath": "/dev/termination-log",
"terminationMessagePolicy": "File"
}
],
"dnsPolicy": "ClusterFirst",
"restartPolicy": "Always",
"schedulerName": "default-scheduler",
"securityContext": {},
"serviceAccount": "jaeger-operator",
"serviceAccountName": "jaeger-operator",
"terminationGracePeriodSeconds": 30
}
}
},
"status": {
"availableReplicas": 1,
"conditions": [
{
"lastTransitionTime": "2021-01-21T01:08:52Z",
"lastUpdateTime": "2021-01-21T01:08:52Z",
"message": "Deployment has minimum availability.",
"reason": "MinimumReplicasAvailable",
"status": "True",
"type": "Available"
},
{
"lastTransitionTime": "2021-01-21T01:08:24Z",
"lastUpdateTime": "2021-01-21T01:08:52Z",
"message": "ReplicaSet \"jaeger-operator-5db4f9d996\" has successfully progressed.",
"reason": "NewReplicaSetAvailable",
"status": "True",
"type": "Progressing"
}
],
"observedGeneration": 1,
"readyReplicas": 1,
"replicas": 1,
"updatedReplicas": 1
}
},
{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": {
"annotations": {
"deployment.kubernetes.io/revision": "1",
"linkerd.io/inject": "disabled",
"prometheus.io/port": "14269",
"prometheus.io/scrape": "true",
"sidecar.istio.io/inject": "false"
},
"creationTimestamp": "2021-01-21T01:08:53Z",
"generation": 1,
"labels": {
"app": "jaeger",
"app.kubernetes.io/component": "all-in-one",
"app.kubernetes.io/instance": "simplest",
"app.kubernetes.io/managed-by": "jaeger-operator",
"app.kubernetes.io/name": "simplest",
"app.kubernetes.io/part-of": "jaeger"
},
"managedFields": [
{
"apiVersion": "apps/v1",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:metadata": {
"f:annotations": {
".": {},
"f:linkerd.io/inject": {},
"f:prometheus.io/port": {},
"f:prometheus.io/scrape": {},
"f:sidecar.istio.io/inject": {}
},
"f:labels": {
".": {},
"f:app": {},
"f:app.kubernetes.io/component": {},
"f:app.kubernetes.io/instance": {},
"f:app.kubernetes.io/managed-by": {},
"f:app.kubernetes.io/name": {},
"f:app.kubernetes.io/part-of": {}
},
"f:ownerReferences": {
".": {},
"k:{\"uid\":\"95d303e8-d347-4f8f-b008-a4da3e44b847\"}": {
".": {},
"f:apiVersion": {},
"f:controller": {},
"f:kind": {},
"f:name": {},
"f:uid": {}
}
}
},
"f:spec": {
"f:progressDeadlineSeconds": {},
"f:replicas": {},
"f:revisionHistoryLimit": {},
"f:selector": {},
"f:strategy": {
"f:rollingUpdate": {
".": {},
"f:maxSurge": {},
"f:maxUnavailable": {}
},
"f:type": {}
},
"f:template": {
"f:metadata": {
"f:annotations": {
".": {},
"f:linkerd.io/inject": {},
"f:prometheus.io/port": {},
"f:prometheus.io/scrape": {},
"f:sidecar.istio.io/inject": {}
},
"f:labels": {
".": {},
"f:app": {},
"f:app.kubernetes.io/component": {},
"f:app.kubernetes.io/instance": {},
"f:app.kubernetes.io/managed-by": {},
"f:app.kubernetes.io/name": {},
"f:app.kubernetes.io/part-of": {}
}
},
"f:spec": {
"f:containers": {
"k:{\"name\":\"jaeger\"}": {
".": {},
"f:args": {},
"f:env": {
".": {},
"k:{\"name\":\"COLLECTOR_ZIPKIN_HTTP_PORT\"}": {
".": {},
"f:name": {},
"f:value": {}
},
"k:{\"name\":\"SPAN_STORAGE_TYPE\"}": {
".": {},
"f:name": {},
"f:value": {}
}
},
"f:image": {},
"f:imagePullPolicy": {},
"f:name": {},
"f:ports": {
".": {},
"k:{\"containerPort\":14267,\"protocol\":\"TCP\"}": {
".": {},
"f:containerPort": {},
"f:name": {},
"f:protocol": {}
},
"k:{\"containerPort\":14268,\"protocol\":\"TCP\"}": {
".": {},
"f:containerPort": {},
"f:name": {},
"f:protocol": {}
},
"k:{\"containerPort\":14269,\"protocol\":\"TCP\"}": {
".": {},
"f:containerPort": {},
"f:name": {},
"f:protocol": {}
},
"k:{\"containerPort\":16686,\"protocol\":\"TCP\"}": {
".": {},
"f:containerPort": {},
"f:name": {},
"f:protocol": {}
},
"k:{\"containerPort\":5775,\"protocol\":\"UDP\"}": {
".": {},
"f:containerPort": {},
"f:name": {},
"f:protocol": {}
},
"k:{\"containerPort\":5778,\"protocol\":\"TCP\"}": {
".": {},
"f:containerPort": {},
"f:name": {},
"f:protocol": {}
},
"k:{\"containerPort\":6831,\"protocol\":\"UDP\"}": {
".": {},
"f:containerPort": {},
"f:name": {},
"f:protocol": {}
},
"k:{\"containerPort\":6832,\"protocol\":\"UDP\"}": {
".": {},
"f:containerPort": {},
"f:name": {},
"f:protocol": {}
},
"k:{\"containerPort\":9411,\"protocol\":\"TCP\"}": {
".": {},
"f:containerPort": {},
"f:name": {},
"f:protocol": {}
}
},
"f:readinessProbe": {
".": {},
"f:failureThreshold": {},
"f:httpGet": {
".": {},
"f:path": {},
"f:port": {},
"f:scheme": {}
},
"f:initialDelaySeconds": {},
"f:periodSeconds": {},
"f:successThreshold": {},
"f:timeoutSeconds": {}
},
"f:resources": {},
"f:terminationMessagePath": {},
"f:terminationMessagePolicy": {},
"f:volumeMounts": {
".": {},
"k:{\"mountPath\":\"/etc/jaeger/sampling\"}": {
".": {},
"f:mountPath": {},
"f:name": {},
"f:readOnly": {}
}
}
}
},
"f:dnsPolicy": {},
"f:restartPolicy": {},
"f:schedulerName": {},
"f:securityContext": {},
"f:serviceAccount": {},
"f:serviceAccountName": {},
"f:terminationGracePeriodSeconds": {},
"f:volumes": {
".": {},
"k:{\"name\":\"simplest-sampling-configuration-volume\"}": {
".": {},
"f:configMap": {
".": {},
"f:defaultMode": {},
"f:items": {},
"f:name": {}
},
"f:name": {}
}
}
}
}
}
},
"manager": "jaeger-operator",
"operation": "Update",
"time": "2021-01-21T01:08:53Z"
},
{
"apiVersion": "apps/v1",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:metadata": {
"f:annotations": {
"f:deployment.kubernetes.io/revision": {}
}
},
"f:status": {
"f:availableReplicas": {},
"f:conditions": {
".": {},
"k:{\"type\":\"Available\"}": {
".": {},
"f:lastTransitionTime": {},
"f:lastUpdateTime": {},
"f:message": {},
"f:reason": {},
"f:status": {},
"f:type": {}
},
"k:{\"type\":\"Progressing\"}": {
".": {},
"f:lastTransitionTime": {},
"f:lastUpdateTime": {},
"f:message": {},
"f:reason": {},
"f:status": {},
"f:type": {}
}
},
"f:observedGeneration": {},
"f:readyReplicas": {},
"f:replicas": {},
"f:updatedReplicas": {}
}
},
"manager": "kube-controller-manager",
"operation": "Update",
"time": "2021-01-21T01:09:04Z"
}
],
"name": "simplest",
"namespace": "default",
"ownerReferences": [
{
"apiVersion": "jaegertracing.io/v1",
"controller": true,
"kind": "Jaeger",
"name": "simplest",
"uid": "95d303e8-d347-4f8f-b008-a4da3e44b847"
}
],
"resourceVersion": "451923",
"selfLink": "/apis/apps/v1/namespaces/default/deployments/simplest",
"uid": "ef190adf-c268-409d-8684-3775e59385bf"
},
"spec": {
"progressDeadlineSeconds": 600,
"replicas": 1,
"revisionHistoryLimit": 10,
"selector": {
"matchLabels": {
"app": "jaeger",
"app.kubernetes.io/component": "all-in-one",
"app.kubernetes.io/instance": "simplest",
"app.kubernetes.io/managed-by": "jaeger-operator",
"app.kubernetes.io/name": "simplest",
"app.kubernetes.io/part-of": "jaeger"
}
},
"strategy": {
"rollingUpdate": {
"maxSurge": "25%",
"maxUnavailable": "25%"
},
"type": "RollingUpdate"
},
"template": {
"metadata": {
"annotations": {
"linkerd.io/inject": "disabled",
"prometheus.io/port": "14269",
"prometheus.io/scrape": "true",
"sidecar.istio.io/inject": "false"
},
"creationTimestamp": null,
"labels": {
"app": "jaeger",
"app.kubernetes.io/component": "all-in-one",
"app.kubernetes.io/instance": "simplest",
"app.kubernetes.io/managed-by": "jaeger-operator",
"app.kubernetes.io/name": "simplest",
"app.kubernetes.io/part-of": "jaeger"
}
},
"spec": {
"containers": [
{
"args": [
"--sampling.strategies-file=/etc/jaeger/sampling/sampling.json"
],
"env": [
{
"name": "SPAN_STORAGE_TYPE",
"value": "memory"
},
{
"name": "COLLECTOR_ZIPKIN_HTTP_PORT",
"value": "9411"
}
],
"image": "jaegertracing/all-in-one:1.14.0",
"imagePullPolicy": "IfNotPresent",
"name": "jaeger",
"ports": [
{
"containerPort": 5775,
"name": "zk-compact-trft",
"protocol": "UDP"
},
{
"containerPort": 5778,
"name": "config-rest",
"protocol": "TCP"
},
{
"containerPort": 6831,
"name": "jg-compact-trft",
"protocol": "UDP"
},
{
"containerPort": 6832,
"name": "jg-binary-trft",
"protocol": "UDP"
},
{
"containerPort": 9411,
"name": "zipkin",
"protocol": "TCP"
},
{
"containerPort": 14267,
"name": "c-tchan-trft",
"protocol": "TCP"
},
{
"containerPort": 14268,
"name": "c-binary-trft",
"protocol": "TCP"
},
{
"containerPort": 16686,
"name": "query",
"protocol": "TCP"
},
{
"containerPort": 14269,
"name": "admin-http",
"protocol": "TCP"
}
],
"readinessProbe": {
"failureThreshold": 3,
"httpGet": {
"path": "/",
"port": 14269,
"scheme": "HTTP"
},
"initialDelaySeconds": 1,
"periodSeconds": 10,
"successThreshold": 1,
"timeoutSeconds": 1
},
"resources": {},
"terminationMessagePath": "/dev/termination-log",
"terminationMessagePolicy": "File",
"volumeMounts": [
{
"mountPath": "/etc/jaeger/sampling",
"name": "simplest-sampling-configuration-volume",
"readOnly": true
}
]
}
],
"dnsPolicy": "ClusterFirst",
"restartPolicy": "Always",
"schedulerName": "default-scheduler",
"securityContext": {},
"serviceAccount": "simplest",
"serviceAccountName": "simplest",
"terminationGracePeriodSeconds": 30,
"volumes": [
{
"configMap": {
"defaultMode": 420,
"items": [
{
"key": "sampling",
"path": "sampling.json"
}
],
"name": "simplest-sampling-configuration"
},
"name": "simplest-sampling-configuration-volume"
}
]
}
}
},
"status": {
"availableReplicas": 1,
"conditions": [
{
"lastTransitionTime": "2021-01-21T01:09:04Z",
"lastUpdateTime": "2021-01-21T01:09:04Z",
"message": "Deployment has minimum availability.",
"reason": "MinimumReplicasAvailable",
"status": "True",
"type": "Available"
},
{
"lastTransitionTime": "2021-01-21T01:08:53Z",
"lastUpdateTime": "2021-01-21T01:09:04Z",
"message": "ReplicaSet \"simplest-85d9df868\" has successfully progressed.",
"reason": "NewReplicaSetAvailable",
"status": "True",
"type": "Progressing"
}
],
"observedGeneration": 1,
"readyReplicas": 1,
"replicas": 1,
"updatedReplicas": 1
}
}
],
"kind": "List",
"metadata": {
"resourceVersion": "",
"selfLink": ""
}
}

View File

@ -0,0 +1,235 @@
{
"apiVersion": "apps/v1",
"kind": "ReplicaSet",
"metadata": {
"annotations": {
"deployment.kubernetes.io/desired-replicas": "1",
"deployment.kubernetes.io/max-replicas": "2",
"deployment.kubernetes.io/revision": "1"
},
"creationTimestamp": "2021-01-21T01:08:24Z",
"generation": 1,
"labels": {
"name": "jaeger-operator",
"pod-template-hash": "5db4f9d996"
},
"managedFields": [
{
"apiVersion": "apps/v1",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:metadata": {
"f:annotations": {
".": {},
"f:deployment.kubernetes.io/desired-replicas": {},
"f:deployment.kubernetes.io/max-replicas": {},
"f:deployment.kubernetes.io/revision": {}
},
"f:labels": {
".": {},
"f:name": {},
"f:pod-template-hash": {}
},
"f:ownerReferences": {
".": {},
"k:{\"uid\":\"baa856ea-2d04-4bbb-b9be-aa5b89c58087\"}": {
".": {},
"f:apiVersion": {},
"f:blockOwnerDeletion": {},
"f:controller": {},
"f:kind": {},
"f:name": {},
"f:uid": {}
}
}
},
"f:spec": {
"f:replicas": {},
"f:selector": {},
"f:template": {
"f:metadata": {
"f:labels": {
".": {},
"f:name": {},
"f:pod-template-hash": {}
}
},
"f:spec": {
"f:containers": {
"k:{\"name\":\"jaeger-operator\"}": {
".": {},
"f:args": {},
"f:env": {
".": {},
"k:{\"name\":\"OPERATOR_NAME\"}": {
".": {},
"f:name": {},
"f:value": {}
},
"k:{\"name\":\"POD_NAME\"}": {
".": {},
"f:name": {},
"f:valueFrom": {
".": {},
"f:fieldRef": {
".": {},
"f:apiVersion": {},
"f:fieldPath": {}
}
}
},
"k:{\"name\":\"POD_NAMESPACE\"}": {
".": {},
"f:name": {},
"f:valueFrom": {
".": {},
"f:fieldRef": {
".": {},
"f:apiVersion": {},
"f:fieldPath": {}
}
}
},
"k:{\"name\":\"WATCH_NAMESPACE\"}": {
".": {},
"f:name": {}
}
},
"f:image": {},
"f:imagePullPolicy": {},
"f:name": {},
"f:ports": {
".": {},
"k:{\"containerPort\":8383,\"protocol\":\"TCP\"}": {
".": {},
"f:containerPort": {},
"f:name": {},
"f:protocol": {}
}
},
"f:resources": {},
"f:terminationMessagePath": {},
"f:terminationMessagePolicy": {}
}
},
"f:dnsPolicy": {},
"f:restartPolicy": {},
"f:schedulerName": {},
"f:securityContext": {},
"f:serviceAccount": {},
"f:serviceAccountName": {},
"f:terminationGracePeriodSeconds": {}
}
}
},
"f:status": {
"f:availableReplicas": {},
"f:fullyLabeledReplicas": {},
"f:observedGeneration": {},
"f:readyReplicas": {},
"f:replicas": {}
}
},
"manager": "kube-controller-manager",
"operation": "Update",
"time": "2021-01-21T01:08:52Z"
}
],
"name": "jaeger-operator-5db4f9d996",
"namespace": "default",
"ownerReferences": [
{
"apiVersion": "apps/v1",
"blockOwnerDeletion": true,
"controller": true,
"kind": "Deployment",
"name": "jaeger-operator",
"uid": "baa856ea-2d04-4bbb-b9be-aa5b89c58087"
}
],
"resourceVersion": "451811",
"selfLink": "/apis/apps/v1/namespaces/default/replicasets/jaeger-operator-5db4f9d996",
"uid": "2efeb411-ff99-434b-a5a2-4e06c2b0afaa"
},
"spec": {
"replicas": 1,
"selector": {
"matchLabels": {
"name": "jaeger-operator",
"pod-template-hash": "5db4f9d996"
}
},
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"name": "jaeger-operator",
"pod-template-hash": "5db4f9d996"
}
},
"spec": {
"containers": [
{
"args": [
"start"
],
"env": [
{
"name": "WATCH_NAMESPACE"
},
{
"name": "POD_NAME",
"valueFrom": {
"fieldRef": {
"apiVersion": "v1",
"fieldPath": "metadata.name"
}
}
},
{
"name": "POD_NAMESPACE",
"valueFrom": {
"fieldRef": {
"apiVersion": "v1",
"fieldPath": "metadata.namespace"
}
}
},
{
"name": "OPERATOR_NAME",
"value": "jaeger-operator"
}
],
"image": "jaegertracing/jaeger-operator:1.14.0",
"imagePullPolicy": "Always",
"name": "jaeger-operator",
"ports": [
{
"containerPort": 8383,
"name": "metrics",
"protocol": "TCP"
}
],
"resources": {},
"terminationMessagePath": "/dev/termination-log",
"terminationMessagePolicy": "File"
}
],
"dnsPolicy": "ClusterFirst",
"restartPolicy": "Always",
"schedulerName": "default-scheduler",
"securityContext": {},
"serviceAccount": "jaeger-operator",
"serviceAccountName": "jaeger-operator",
"terminationGracePeriodSeconds": 30
}
}
},
"status": {
"availableReplicas": 1,
"fullyLabeledReplicas": 1,
"observedGeneration": 1,
"readyReplicas": 1,
"replicas": 1
}
}

View File

@ -0,0 +1,403 @@
{
"apiVersion": "apps/v1",
"kind": "StatefulSet",
"metadata": {
"creationTimestamp": "2021-01-21T01:13:12Z",
"generation": 1,
"labels": {
"alertmanager": "main"
},
"managedFields": [
{
"apiVersion": "apps/v1",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:metadata": {
"f:labels": {
".": {},
"f:alertmanager": {}
},
"f:ownerReferences": {
".": {},
"k:{\"uid\":\"e6a6358b-646a-4171-8737-beb6c2b9ffaf\"}": {
".": {},
"f:apiVersion": {},
"f:blockOwnerDeletion": {},
"f:controller": {},
"f:kind": {},
"f:name": {},
"f:uid": {}
}
}
},
"f:spec": {
"f:podManagementPolicy": {},
"f:replicas": {},
"f:revisionHistoryLimit": {},
"f:selector": {},
"f:serviceName": {},
"f:template": {
"f:metadata": {
"f:labels": {
".": {},
"f:alertmanager": {},
"f:app": {}
}
},
"f:spec": {
"f:containers": {
"k:{\"name\":\"alertmanager\"}": {
".": {},
"f:args": {},
"f:env": {
".": {},
"k:{\"name\":\"POD_IP\"}": {
".": {},
"f:name": {},
"f:valueFrom": {
".": {},
"f:fieldRef": {
".": {},
"f:apiVersion": {},
"f:fieldPath": {}
}
}
}
},
"f:image": {},
"f:imagePullPolicy": {},
"f:livenessProbe": {
".": {},
"f:failureThreshold": {},
"f:httpGet": {
".": {},
"f:path": {},
"f:port": {},
"f:scheme": {}
},
"f:periodSeconds": {},
"f:successThreshold": {},
"f:timeoutSeconds": {}
},
"f:name": {},
"f:ports": {
".": {},
"k:{\"containerPort\":9093,\"protocol\":\"TCP\"}": {
".": {},
"f:containerPort": {},
"f:name": {},
"f:protocol": {}
},
"k:{\"containerPort\":9094,\"protocol\":\"TCP\"}": {
".": {},
"f:containerPort": {},
"f:name": {},
"f:protocol": {}
},
"k:{\"containerPort\":9094,\"protocol\":\"UDP\"}": {
".": {},
"f:containerPort": {},
"f:name": {},
"f:protocol": {}
}
},
"f:readinessProbe": {
".": {},
"f:failureThreshold": {},
"f:httpGet": {
".": {},
"f:path": {},
"f:port": {},
"f:scheme": {}
},
"f:initialDelaySeconds": {},
"f:periodSeconds": {},
"f:successThreshold": {},
"f:timeoutSeconds": {}
},
"f:resources": {
".": {},
"f:requests": {
".": {},
"f:memory": {}
}
},
"f:terminationMessagePath": {},
"f:terminationMessagePolicy": {},
"f:volumeMounts": {
".": {},
"k:{\"mountPath\":\"/alertmanager\"}": {
".": {},
"f:mountPath": {},
"f:name": {}
},
"k:{\"mountPath\":\"/etc/alertmanager/config\"}": {
".": {},
"f:mountPath": {},
"f:name": {}
}
}
},
"k:{\"name\":\"config-reloader\"}": {
".": {},
"f:args": {},
"f:image": {},
"f:imagePullPolicy": {},
"f:name": {},
"f:resources": {
".": {},
"f:limits": {
".": {},
"f:cpu": {},
"f:memory": {}
}
},
"f:terminationMessagePath": {},
"f:terminationMessagePolicy": {},
"f:volumeMounts": {
".": {},
"k:{\"mountPath\":\"/etc/alertmanager/config\"}": {
".": {},
"f:mountPath": {},
"f:name": {},
"f:readOnly": {}
}
}
}
},
"f:dnsPolicy": {},
"f:nodeSelector": {
".": {},
"f:kubernetes.io/os": {}
},
"f:restartPolicy": {},
"f:schedulerName": {},
"f:securityContext": {
".": {},
"f:fsGroup": {},
"f:runAsNonRoot": {},
"f:runAsUser": {}
},
"f:serviceAccount": {},
"f:serviceAccountName": {},
"f:terminationGracePeriodSeconds": {},
"f:volumes": {
".": {},
"k:{\"name\":\"alertmanager-main-db\"}": {
".": {},
"f:emptyDir": {},
"f:name": {}
},
"k:{\"name\":\"config-volume\"}": {
".": {},
"f:name": {},
"f:secret": {
".": {},
"f:defaultMode": {},
"f:secretName": {}
}
}
}
}
},
"f:updateStrategy": {
"f:type": {}
}
},
"f:status": {
"f:replicas": {}
}
},
"manager": "operator",
"operation": "Update",
"time": "2021-01-21T01:13:12Z"
}
],
"name": "alertmanager-main",
"namespace": "monitoring",
"ownerReferences": [
{
"apiVersion": "monitoring.coreos.com/v1",
"blockOwnerDeletion": true,
"controller": true,
"kind": "Alertmanager",
"name": "main",
"uid": "e6a6358b-646a-4171-8737-beb6c2b9ffaf"
}
],
"resourceVersion": "452929",
"selfLink": "/apis/apps/v1/namespaces/monitoring/statefulsets/alertmanager-main",
"uid": "3c488e7e-420c-4515-b377-5dc3ee082744"
},
"spec": {
"podManagementPolicy": "Parallel",
"replicas": 1,
"revisionHistoryLimit": 10,
"selector": {
"matchLabels": {
"alertmanager": "main",
"app": "alertmanager"
}
},
"serviceName": "alertmanager-operated",
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"alertmanager": "main",
"app": "alertmanager"
}
},
"spec": {
"containers": [
{
"args": [
"--config.file=/etc/alertmanager/config/alertmanager.yaml",
"--storage.path=/alertmanager",
"--data.retention=120h",
"--cluster.listen-address=",
"--web.listen-address=:9093",
"--web.route-prefix=/",
"--cluster.peer=alertmanager-main-0.alertmanager-operated:9094"
],
"env": [
{
"name": "POD_IP",
"valueFrom": {
"fieldRef": {
"apiVersion": "v1",
"fieldPath": "status.podIP"
}
}
}
],
"image": "quay.io/prometheus/alertmanager:v0.21.0",
"imagePullPolicy": "IfNotPresent",
"livenessProbe": {
"failureThreshold": 10,
"httpGet": {
"path": "/-/healthy",
"port": "web",
"scheme": "HTTP"
},
"periodSeconds": 10,
"successThreshold": 1,
"timeoutSeconds": 3
},
"name": "alertmanager",
"ports": [
{
"containerPort": 9093,
"name": "web",
"protocol": "TCP"
},
{
"containerPort": 9094,
"name": "mesh-tcp",
"protocol": "TCP"
},
{
"containerPort": 9094,
"name": "mesh-udp",
"protocol": "UDP"
}
],
"readinessProbe": {
"failureThreshold": 10,
"httpGet": {
"path": "/-/ready",
"port": "web",
"scheme": "HTTP"
},
"initialDelaySeconds": 3,
"periodSeconds": 5,
"successThreshold": 1,
"timeoutSeconds": 3
},
"resources": {
"requests": {
"memory": "200Mi"
}
},
"terminationMessagePath": "/dev/termination-log",
"terminationMessagePolicy": "FallbackToLogsOnError",
"volumeMounts": [
{
"mountPath": "/etc/alertmanager/config",
"name": "config-volume"
},
{
"mountPath": "/alertmanager",
"name": "alertmanager-main-db"
}
]
},
{
"args": [
"-webhook-url=http://localhost:9093/-/reload",
"-volume-dir=/etc/alertmanager/config"
],
"image": "jimmidyson/configmap-reload:v0.3.0",
"imagePullPolicy": "IfNotPresent",
"name": "config-reloader",
"resources": {
"limits": {
"cpu": "100m",
"memory": "25Mi"
}
},
"terminationMessagePath": "/dev/termination-log",
"terminationMessagePolicy": "FallbackToLogsOnError",
"volumeMounts": [
{
"mountPath": "/etc/alertmanager/config",
"name": "config-volume",
"readOnly": true
}
]
}
],
"dnsPolicy": "ClusterFirst",
"nodeSelector": {
"kubernetes.io/os": "linux"
},
"restartPolicy": "Always",
"schedulerName": "default-scheduler",
"securityContext": {
"fsGroup": 2000,
"runAsNonRoot": true,
"runAsUser": 1000
},
"serviceAccount": "alertmanager-main",
"serviceAccountName": "alertmanager-main",
"terminationGracePeriodSeconds": 120,
"volumes": [
{
"name": "config-volume",
"secret": {
"defaultMode": 420,
"secretName": "alertmanager-main"
}
},
{
"emptyDir": {},
"name": "alertmanager-main-db"
}
]
}
},
"updateStrategy": {
"type": "RollingUpdate"
}
},
"status": {
"collisionCount": 0,
"currentReplicas": 1,
"currentRevision": "alertmanager-main-6674894c9d",
"observedGeneration": 1,
"readyReplicas": 1,
"replicas": 1,
"updateRevision": "alertmanager-main-6674894c9d",
"updatedReplicas": 1
}
}

View File

@ -0,0 +1,59 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package autoscaling
import (
"context"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/Uptycs/kubequery/internal/k8s"
v1 "k8s.io/api/autoscaling/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type horizontalPodAutoscaler struct {
k8s.CommonNamespacedFields
v1.HorizontalPodAutoscalerSpec
v1.HorizontalPodAutoscalerStatus
}
// HorizontalPodAutoscalersColumns returns kubernetes horizontal pod autoscaler fields as Osquery table columns.
func HorizontalPodAutoscalersColumns() []table.ColumnDefinition {
return k8s.GetSchema(&horizontalPodAutoscaler{})
}
// HorizontalPodAutoscalerGenerate generates the kubernetes horizontal pod autoscalers as Osquery table data.
func HorizontalPodAutoscalerGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
options := metav1.ListOptions{}
results := make([]map[string]string, 0)
for {
hpas, err := k8s.GetClient().AutoscalingV1().HorizontalPodAutoscalers(metav1.NamespaceAll).List(ctx, options)
if err != nil {
return nil, err
}
for _, hpa := range hpas.Items {
item := &horizontalPodAutoscaler{
CommonNamespacedFields: k8s.GetCommonNamespacedFields(hpa.ObjectMeta),
HorizontalPodAutoscalerSpec: hpa.Spec,
HorizontalPodAutoscalerStatus: hpa.Status,
}
results = append(results, k8s.ToMap(item))
}
if hpas.Continue == "" {
break
}
options.Continue = hpas.Continue
}
return results, nil
}

View File

@ -0,0 +1,73 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package autoscaling
import (
"context"
"testing"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/Uptycs/kubequery/internal/k8s"
"github.com/stretchr/testify/assert"
v1 "k8s.io/api/autoscaling/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes/fake"
)
func TestHorizontalPodAutoscalerGenerate(t *testing.T) {
i32 := int32(456)
i64 := int64(123)
k8s.SetClient(fake.NewSimpleClientset(&v1.HorizontalPodAutoscaler{
ObjectMeta: metav1.ObjectMeta{
Name: "hpa1",
Namespace: "n123",
UID: types.UID("1234"),
Labels: map[string]string{"a": "b"},
},
Spec: v1.HorizontalPodAutoscalerSpec{
MinReplicas: &i32,
MaxReplicas: i32,
TargetCPUUtilizationPercentage: &i32,
ScaleTargetRef: v1.CrossVersionObjectReference{
Name: "blah",
},
},
Status: v1.HorizontalPodAutoscalerStatus{
ObservedGeneration: &i64,
LastScaleTime: &metav1.Time{},
CurrentReplicas: i32,
DesiredReplicas: i32,
CurrentCPUUtilizationPercentage: &i32,
},
}), types.UID("hello"), "")
hpas, err := HorizontalPodAutoscalerGenerate(context.TODO(), table.QueryContext{})
assert.Nil(t, err)
assert.Equal(t, []map[string]string{
{
"cluster_uid": "hello",
"creation_timestamp": "0",
"current_cpu_utilization_percentage": "456",
"current_replicas": "456",
"desired_replicas": "456",
"labels": "{\"a\":\"b\"}",
"last_scale_time": "0",
"max_replicas": "456",
"min_replicas": "456",
"name": "hpa1",
"namespace": "n123",
"observed_generation": "123",
"scale_target_ref": "{\"kind\":\"\",\"name\":\"blah\"}",
"target_cpu_utilization_percentage": "456",
"uid": "1234",
},
}, hpas)
}

View File

@ -0,0 +1,85 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package batch
import (
"context"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/Uptycs/kubequery/internal/k8s"
v1 "k8s.io/api/batch/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type cronJob struct {
k8s.CommonNamespacedFields
k8s.CommonPodFields
v1.CronJobStatus
Schedule string
StartingDeadlineSeconds *int64
ConcurrencyPolicy v1.ConcurrencyPolicy
Suspend *bool
SuccessfulJobsHistoryLimit *int32
FailedJobsHistoryLimit *int32
Parallelism *int32
Completions *int32
JobActiveDeadlineSeconds *int64
BackoffLimit *int32
Selector *metav1.LabelSelector
ManualSelector *bool
TTLSecondsAfterFinished *int32
}
// CronJobColumns returns kubernetes cron job fields as Osquery table columns.
func CronJobColumns() []table.ColumnDefinition {
return k8s.GetSchema(&cronJob{})
}
// CronJobsGenerate generates the kubernetes cron jobs as Osquery table data.
func CronJobsGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
options := metav1.ListOptions{}
results := make([]map[string]string, 0)
for {
cjs, err := k8s.GetClient().BatchV1().CronJobs(metav1.NamespaceAll).List(ctx, options)
if err != nil {
return nil, err
}
for _, cj := range cjs.Items {
item := &cronJob{
CommonNamespacedFields: k8s.GetCommonNamespacedFields(cj.ObjectMeta),
CommonPodFields: k8s.GetCommonPodFields(cj.Spec.JobTemplate.Spec.Template.Spec),
CronJobStatus: cj.Status,
Schedule: cj.Spec.Schedule,
StartingDeadlineSeconds: cj.Spec.StartingDeadlineSeconds,
ConcurrencyPolicy: cj.Spec.ConcurrencyPolicy,
Suspend: cj.Spec.Suspend,
SuccessfulJobsHistoryLimit: cj.Spec.SuccessfulJobsHistoryLimit,
FailedJobsHistoryLimit: cj.Spec.FailedJobsHistoryLimit,
Parallelism: cj.Spec.JobTemplate.Spec.Parallelism,
Completions: cj.Spec.JobTemplate.Spec.Completions,
JobActiveDeadlineSeconds: cj.Spec.JobTemplate.Spec.ActiveDeadlineSeconds,
BackoffLimit: cj.Spec.JobTemplate.Spec.BackoffLimit,
Selector: cj.Spec.JobTemplate.Spec.Selector,
ManualSelector: cj.Spec.JobTemplate.Spec.ManualSelector,
TTLSecondsAfterFinished: cj.Spec.JobTemplate.Spec.TTLSecondsAfterFinished,
}
results = append(results, k8s.ToMap(item))
}
if cjs.Continue == "" {
break
}
options.Continue = cjs.Continue
}
return results, nil
}

View File

@ -0,0 +1,93 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package batch
import (
"context"
"testing"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/Uptycs/kubequery/internal/k8s"
"github.com/stretchr/testify/assert"
v1 "k8s.io/api/batch/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes/fake"
)
func TestCronJobsGenerate(t *testing.T) {
i32 := int32(456)
i64 := int64(123)
b := bool(true)
k8s.SetClient(fake.NewSimpleClientset(&v1.CronJob{
ObjectMeta: metav1.ObjectMeta{
Name: "cj1",
Namespace: "n123",
UID: types.UID("1234"),
Labels: map[string]string{"a": "b"},
},
Spec: v1.CronJobSpec{
Schedule: "s1",
StartingDeadlineSeconds: &i64,
ConcurrencyPolicy: v1.AllowConcurrent,
Suspend: &b,
SuccessfulJobsHistoryLimit: &i32,
FailedJobsHistoryLimit: &i32,
JobTemplate: v1.JobTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Name: "job1",
Namespace: "n123",
UID: types.UID("1234"),
Labels: map[string]string{"a": "b"},
},
Spec: v1.JobSpec{
Parallelism: &i32,
Completions: &i32,
ActiveDeadlineSeconds: &i64,
BackoffLimit: &i32,
ManualSelector: &b,
TTLSecondsAfterFinished: &i32,
},
},
},
Status: v1.CronJobStatus{
LastScheduleTime: &metav1.Time{},
},
}), types.UID("hello"), "")
cjs, err := CronJobsGenerate(context.TODO(), table.QueryContext{})
assert.Nil(t, err)
assert.Equal(t, []map[string]string{
{
"backoff_limit": "456",
"cluster_uid": "hello",
"completions": "456",
"concurrency_policy": "Allow",
"creation_timestamp": "0",
"failed_jobs_history_limit": "456",
"host_ipc": "0",
"host_network": "0",
"host_pid": "0",
"job_active_deadline_seconds": "123",
"labels": "{\"a\":\"b\"}",
"last_schedule_time": "0",
"manual_selector": "1",
"name": "cj1",
"namespace": "n123",
"parallelism": "456",
"schedule": "s1",
"starting_deadline_seconds": "123",
"successful_jobs_history_limit": "456",
"suspend": "1",
"ttl_seconds_after_finished": "456",
"uid": "1234",
},
}, cjs)
}

View File

@ -0,0 +1,73 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package batch
import (
"context"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/Uptycs/kubequery/internal/k8s"
v1 "k8s.io/api/batch/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type job struct {
k8s.CommonNamespacedFields
k8s.CommonPodFields
v1.JobStatus
Parallelism *int32
Completions *int32
JobActiveDeadlineSeconds *int64
BackoffLimit *int32
Selector *metav1.LabelSelector
ManualSelector *bool
TTLSecondsAfterFinished *int32
}
// JobColumns returns kubernetes job fields as Osquery table columns.
func JobColumns() []table.ColumnDefinition {
return k8s.GetSchema(&job{})
}
// JobsGenerate generates the kubernetes jobs as Osquery table data.
func JobsGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
options := metav1.ListOptions{}
results := make([]map[string]string, 0)
for {
jobs, err := k8s.GetClient().BatchV1().Jobs(metav1.NamespaceAll).List(ctx, options)
if err != nil {
return nil, err
}
for _, j := range jobs.Items {
item := &job{
CommonNamespacedFields: k8s.GetCommonNamespacedFields(j.ObjectMeta),
CommonPodFields: k8s.GetCommonPodFields(j.Spec.Template.Spec),
JobStatus: j.Status,
Parallelism: j.Spec.Parallelism,
Completions: j.Spec.Completions,
JobActiveDeadlineSeconds: j.Spec.ActiveDeadlineSeconds,
BackoffLimit: j.Spec.BackoffLimit,
Selector: j.Spec.Selector,
ManualSelector: j.Spec.ManualSelector,
TTLSecondsAfterFinished: j.Spec.TTLSecondsAfterFinished,
}
results = append(results, k8s.ToMap(item))
}
if jobs.Continue == "" {
break
}
options.Continue = jobs.Continue
}
return results, nil
}

View File

@ -0,0 +1,88 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package batch
import (
"context"
"testing"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/Uptycs/kubequery/internal/k8s"
"github.com/stretchr/testify/assert"
v1 "k8s.io/api/batch/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes/fake"
)
func TestJobsGenerate(t *testing.T) {
i32 := int32(456)
i64 := int64(123)
b := bool(true)
k8s.SetClient(fake.NewSimpleClientset(&v1.Job{
ObjectMeta: metav1.ObjectMeta{
Name: "job1",
Namespace: "n123",
UID: types.UID("1234"),
Labels: map[string]string{"a": "b"},
},
Spec: v1.JobSpec{
Parallelism: &i32,
Completions: &i32,
ActiveDeadlineSeconds: &i64,
BackoffLimit: &i32,
ManualSelector: &b,
TTLSecondsAfterFinished: &i32,
},
Status: v1.JobStatus{
StartTime: &metav1.Time{},
Active: i32,
Succeeded: i32,
Failed: i32,
CompletionTime: nil,
Conditions: []v1.JobCondition{
{
Type: v1.JobComplete,
Status: metav1.DryRunAll,
LastTransitionTime: metav1.Time{},
Reason: "reason",
Message: "message",
},
},
},
}), types.UID("hello"), "")
js, err := JobsGenerate(context.TODO(), table.QueryContext{})
assert.Nil(t, err)
assert.Equal(t, []map[string]string{
{
"active": "456",
"backoff_limit": "456",
"cluster_uid": "hello",
"completions": "456",
"conditions": "[{\"type\":\"Complete\",\"status\":\"All\",\"lastProbeTime\":null,\"lastTransitionTime\":null,\"reason\":\"reason\",\"message\":\"message\"}]",
"creation_timestamp": "0",
"failed": "456",
"host_ipc": "0",
"host_network": "0",
"host_pid": "0",
"job_active_deadline_seconds": "123",
"labels": "{\"a\":\"b\"}",
"manual_selector": "1",
"name": "job1",
"namespace": "n123",
"parallelism": "456",
"start_time": "0",
"succeeded": "456",
"ttl_seconds_after_finished": "456",
"uid": "1234",
},
}, js)
}

View File

@ -0,0 +1,125 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package k8s
import (
"context"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"sync"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/util/homedir"
)
var (
lock sync.Mutex
clientset kubernetes.Interface
clusterUID types.UID
clusterName string
)
func initClientset(config *rest.Config) error {
if config == nil {
conf, err := rest.InClusterConfig()
if err != nil {
if home := homedir.HomeDir(); home != "" {
content, ferr := ioutil.ReadFile(filepath.Join(home, ".kube", "config"))
if content != nil && ferr == nil {
conf, err = clientcmd.RESTConfigFromKubeConfig(content)
if err != nil {
return err
}
}
}
}
config = conf
}
// Suppress deprecation warnings
config.WarningHandler = rest.NoWarnings{}
var err error
clientset, err = kubernetes.NewForConfig(config)
if err != nil {
return err
}
return nil
}
func initUID() error {
ks, err := GetClient().CoreV1().Namespaces().Get(context.TODO(), "kube-system", v1.GetOptions{})
if err != nil {
return err
}
clusterUID = ks.UID
if ks.ClusterName == "" {
clusterName, err = os.Hostname()
if err != nil {
fmt.Println("Unable to determine hostname: ", err.Error())
}
} else {
clusterName = ks.ClusterName
}
return nil
}
// Init creates in-cluster kubernetes configuration and a client set using the configuration.
// This returns error if KUBERNETES_SERVICE_HOST or KUBERNETES_SERVICE_PORT environment variables are not set.
func Init() error {
lock.Lock()
defer lock.Unlock()
err := initClientset(nil)
if err != nil {
return err
}
err = initUID()
if err != nil {
return err
}
return nil
}
// GetClient returns kubernetes interface that can be used to communicate with API server.
func GetClient() kubernetes.Interface {
return clientset
}
// GetClusterUID returns unique identifier for the current kubernetes cluster.
// This is same as the kube-system namespace UID.
func GetClusterUID() types.UID {
return clusterUID
}
// GetClusterName returns cluster name provided by the kubernates API.
// If it is empty, it uses the pod hostname which should be set to the cluster name.
func GetClusterName() string {
return clusterName
}
// SetClient is helper function to override the kubernetes interface with fake one for testing.
func SetClient(client kubernetes.Interface, uid types.UID, name string) {
lock.Lock()
defer lock.Unlock()
clientset = client
clusterUID = uid
clusterName = name
}

View File

@ -0,0 +1,33 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package k8s
import (
"testing"
"github.com/stretchr/testify/assert"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes/fake"
)
func TestGetClient(t *testing.T) {
SetClient(fake.NewSimpleClientset(), types.UID("uid"), "cluster-name")
assert.NotNil(t, GetClient(), "Clientset should be valid")
}
func TestGetClusterUID(t *testing.T) {
SetClient(fake.NewSimpleClientset(), types.UID("uid"), "cluster-name")
assert.Equal(t, types.UID("uid"), GetClusterUID())
}
func TestGetClusterName(t *testing.T) {
SetClient(fake.NewSimpleClientset(), types.UID("uid"), "cluster-name")
assert.Equal(t, "cluster-name", GetClusterName())
}

View File

@ -0,0 +1,694 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package k8s
import (
"github.com/google/uuid"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
)
// CommonFields contains fields common to most tables. Contents are derived from kubernetes ObjectMeta.
// This is used for kubernetes resources that are not namespaced.
type CommonFields struct {
UID types.UID
ClusterName string
ClusterUID types.UID
Name string
CreationTimestamp metav1.Time
Labels map[string]string
Annotations map[string]string
}
// GetCommonFields returns CommonFields struct from the provided kubernetes ObjectMeta.
func GetCommonFields(obj metav1.ObjectMeta) CommonFields {
return CommonFields{
UID: obj.UID,
ClusterName: GetClusterName(),
ClusterUID: GetClusterUID(),
Name: obj.Name,
CreationTimestamp: obj.CreationTimestamp,
Labels: obj.Labels,
Annotations: obj.Annotations,
}
}
// CommonNamespacedFields contains fields common to most tables. Contents are derived from kubernetes ObjectMeta.
// This is used for kubernetes resources that are namespaced.
type CommonNamespacedFields struct {
UID types.UID
ClusterName string
ClusterUID types.UID
Name string
Namespace string
CreationTimestamp metav1.Time
Labels map[string]string
Annotations map[string]string
}
// GetCommonNamespacedFields returns CommonNamespacedFields struct from the provided kubernetes ObjectMeta.
func GetCommonNamespacedFields(obj metav1.ObjectMeta) CommonNamespacedFields {
return CommonNamespacedFields{
UID: obj.UID,
ClusterName: GetClusterName(),
ClusterUID: GetClusterUID(),
Name: obj.Name,
Namespace: obj.Namespace,
CreationTimestamp: obj.CreationTimestamp,
Labels: obj.Labels,
Annotations: obj.Annotations,
}
}
// GetParentCommonNamespacedFields returns CommonNamespacedFields struct from the parent ObjectMeta creating a UID using parent UID + provided name.
func GetParentCommonNamespacedFields(parent metav1.ObjectMeta, name string) CommonNamespacedFields {
uid := uuid.NewSHA1(uuid.NameSpaceDNS, []byte(string(parent.UID)+name)).String()
return CommonNamespacedFields{
UID: types.UID(uid),
ClusterName: GetClusterName(),
ClusterUID: GetClusterUID(),
Name: name,
Namespace: parent.Namespace,
CreationTimestamp: parent.CreationTimestamp,
Labels: parent.Labels,
Annotations: parent.Annotations,
}
}
// SELinuxOptionsFields contains SELinux options as a flat structure.
type SELinuxOptionsFields struct {
SELinuxOptionsUser string
SELinuxOptionsRole string
SELinuxOptionsType string
SELinuxOptionsLevel string
}
// WindowsOptionsFields contains Windows options as a flat structure.
type WindowsOptionsFields struct {
WindowsOptionsGMSACredentialSpecName *string
WindowsOptionsGMSACredentialSpec *string
WindowsOptionsRunAsUserName *string
}
// SeccompProfileFields contains Seccomp profile options as a flat structure.
type SeccompProfileFields struct {
SeccompProfileType v1.SeccompProfileType
SeccompProfileLocalhostProfile *string
}
// CommonSecurityContextFields contains all security options common to a pod and container.
type CommonSecurityContextFields struct {
SELinuxOptionsFields
WindowsOptionsFields
SeccompProfileFields
RunAsUser *int64
RunAsGroup *int64
RunAsNonRoot *bool
}
// PodSecurityContextFields contains all security options specific to a pod.
type PodSecurityContextFields struct {
CommonSecurityContextFields
SupplementalGroups []int64
FSGroup *int64
Sysctls []v1.Sysctl
FSGroupChangePolicy *v1.PodFSGroupChangePolicy
}
// SecurityContextFields contains all securoty options specific to a container.
type SecurityContextFields struct {
CommonSecurityContextFields
CapabilitiesAdd []v1.Capability
CapabilitiesDrop []v1.Capability
Privileged *bool
ReadOnlyRootFilesystem *bool
AllowPrivilegeEscalation *bool
ProcMount *v1.ProcMountType
}
// AffinityFields struct holds flat affinity fields.
type AffinityFields struct {
NodeAffinity *v1.NodeAffinity
PodAffinity *v1.PodAffinity
PodAntiAffinity *v1.PodAntiAffinity
}
// DNSConfigFields struct holds DNS configuration fields.
type DNSConfigFields struct {
DNSConfigNameservers []string
DNSConfigSearches []string
DNSConfigOptions []v1.PodDNSConfigOption
}
// CommonPodFields contains relevant fields from pod specification.
// This flattens some of the embedded structures like security context, DNS config etc.
type CommonPodFields struct {
PodSecurityContextFields
AffinityFields
DNSConfigFields
NodeSelector map[string]string
RestartPolicy v1.RestartPolicy
TerminationGracePeriodSeconds *int64
ActiveDeadlineSeconds *int64
DNSPolicy v1.DNSPolicy
ServiceAccountName string
AutomountServiceAccountToken *bool
NodeName string
HostNetwork bool
HostPID bool
HostIPC bool
ShareProcessNamespace *bool
ImagePullSecrets []v1.LocalObjectReference
Hostname string
Subdomain string
SchedulerName string
Tolerations []v1.Toleration
HostAliases []v1.HostAlias
PriorityClassName string
Priority *int32
ReadinessGates []v1.PodReadinessGate
RuntimeClassName *string
EnableServiceLinks *bool
PreemptionPolicy *v1.PreemptionPolicy
Overhead v1.ResourceList
TopologySpreadConstraints []v1.TopologySpreadConstraint
SetHostnameAsFQDN *bool
}
// GetCommonPodFields converts pod specification to CommonPodFields structure.
// This flattens some of the embedded structures like security context, DNS config etc.
func GetCommonPodFields(p v1.PodSpec) CommonPodFields {
item := CommonPodFields{
NodeSelector: p.NodeSelector,
RestartPolicy: p.RestartPolicy,
TerminationGracePeriodSeconds: p.TerminationGracePeriodSeconds,
ActiveDeadlineSeconds: p.ActiveDeadlineSeconds,
DNSPolicy: p.DNSPolicy,
ServiceAccountName: p.ServiceAccountName,
AutomountServiceAccountToken: p.AutomountServiceAccountToken,
NodeName: p.NodeName,
HostNetwork: p.HostNetwork,
HostPID: p.HostPID,
HostIPC: p.HostIPC,
ShareProcessNamespace: p.ShareProcessNamespace,
ImagePullSecrets: p.ImagePullSecrets,
Hostname: p.Hostname,
Subdomain: p.Subdomain,
SchedulerName: p.SchedulerName,
Tolerations: p.Tolerations,
HostAliases: p.HostAliases,
PriorityClassName: p.PriorityClassName,
Priority: p.Priority,
ReadinessGates: p.ReadinessGates,
RuntimeClassName: p.RuntimeClassName,
EnableServiceLinks: p.EnableServiceLinks,
PreemptionPolicy: p.PreemptionPolicy,
Overhead: p.Overhead,
TopologySpreadConstraints: p.TopologySpreadConstraints,
SetHostnameAsFQDN: p.SetHostnameAsFQDN,
}
if p.Affinity != nil {
item.NodeAffinity = p.Affinity.NodeAffinity
item.PodAffinity = p.Affinity.PodAffinity
item.PodAntiAffinity = p.Affinity.PodAntiAffinity
}
if p.DNSConfig != nil {
item.DNSConfigNameservers = p.DNSConfig.Nameservers
item.DNSConfigSearches = p.DNSConfig.Searches
item.DNSConfigOptions = p.DNSConfig.Options
}
if p.SecurityContext != nil {
item.RunAsUser = p.SecurityContext.RunAsUser
item.RunAsGroup = p.SecurityContext.RunAsGroup
item.RunAsNonRoot = p.SecurityContext.RunAsNonRoot
item.SupplementalGroups = p.SecurityContext.SupplementalGroups
item.Sysctls = p.SecurityContext.Sysctls
item.FSGroup = p.SecurityContext.FSGroup
item.FSGroupChangePolicy = p.SecurityContext.FSGroupChangePolicy
if p.SecurityContext.SeccompProfile != nil {
item.SeccompProfileType = p.SecurityContext.SeccompProfile.Type
item.SeccompProfileLocalhostProfile = p.SecurityContext.SeccompProfile.LocalhostProfile
}
if p.SecurityContext.SELinuxOptions != nil {
item.SELinuxOptionsLevel = p.SecurityContext.SELinuxOptions.Level
item.SELinuxOptionsRole = p.SecurityContext.SELinuxOptions.Role
item.SELinuxOptionsType = p.SecurityContext.SELinuxOptions.Type
item.SELinuxOptionsUser = p.SecurityContext.SELinuxOptions.User
}
if p.SecurityContext.WindowsOptions != nil {
item.WindowsOptionsRunAsUserName = p.SecurityContext.WindowsOptions.RunAsUserName
item.WindowsOptionsGMSACredentialSpec = p.SecurityContext.WindowsOptions.GMSACredentialSpec
item.WindowsOptionsGMSACredentialSpecName = p.SecurityContext.WindowsOptions.GMSACredentialSpecName
}
}
return item
}
// CommonContainerFields contains relevant fields from container specification.
// This flattens some of the embedded structures like security context.
type CommonContainerFields struct {
SecurityContextFields
TargetContainerName string
Image string
Command []string
Args []string
WorkingDir string
Ports []v1.ContainerPort
EnvFrom []v1.EnvFromSource
Env []v1.EnvVar
ResourceLimits v1.ResourceList
ResourceRequests v1.ResourceList
VolumeMounts []v1.VolumeMount
VolumeDevices []v1.VolumeDevice
LivenessProbe *v1.Probe
ReadinessProbe *v1.Probe
StartupProbe *v1.Probe
Lifecycle *v1.Lifecycle
TerminationMessagePath string
TerminationMessagePolicy v1.TerminationMessagePolicy
ImagePullPolicy v1.PullPolicy
Stdin bool
StdinOnce bool
TTY bool
}
// GetCommonContainerFields converts container specification to CommonContainerFields structure.
// This flattens some of the embedded structures like security context.
func GetCommonContainerFields(c v1.Container) CommonContainerFields {
item := CommonContainerFields{
Image: c.Image,
Command: c.Command,
Args: c.Args,
WorkingDir: c.WorkingDir,
Ports: c.Ports,
EnvFrom: c.EnvFrom,
Env: c.Env,
ResourceLimits: c.Resources.Limits,
ResourceRequests: c.Resources.Requests,
VolumeMounts: c.VolumeMounts,
VolumeDevices: c.VolumeDevices,
LivenessProbe: c.LivenessProbe,
ReadinessProbe: c.ReadinessProbe,
StartupProbe: c.StartupProbe,
Lifecycle: c.Lifecycle,
TerminationMessagePath: c.TerminationMessagePath,
TerminationMessagePolicy: c.TerminationMessagePolicy,
ImagePullPolicy: c.ImagePullPolicy,
Stdin: c.Stdin,
StdinOnce: c.StdinOnce,
TTY: c.TTY,
}
copyContainerSecurityContext(&item, c.SecurityContext)
return item
}
// GetCommonEphemeralContainerFields converts ephemeral container specification to CommonContainerFields.
// This flattens some of the embedded structures like security context.
// Ephemeral container contains one additional field (TargetContainerName) on top of container.
func GetCommonEphemeralContainerFields(c v1.EphemeralContainer) CommonContainerFields {
item := CommonContainerFields{
TargetContainerName: c.TargetContainerName,
Image: c.Image,
Command: c.Command,
Args: c.Args,
WorkingDir: c.WorkingDir,
Ports: c.Ports,
EnvFrom: c.EnvFrom,
Env: c.Env,
ResourceLimits: c.Resources.Limits,
ResourceRequests: c.Resources.Requests,
VolumeMounts: c.VolumeMounts,
VolumeDevices: c.VolumeDevices,
LivenessProbe: c.LivenessProbe,
ReadinessProbe: c.ReadinessProbe,
StartupProbe: c.StartupProbe,
Lifecycle: c.Lifecycle,
TerminationMessagePath: c.TerminationMessagePath,
TerminationMessagePolicy: c.TerminationMessagePolicy,
ImagePullPolicy: c.ImagePullPolicy,
Stdin: c.Stdin,
StdinOnce: c.StdinOnce,
TTY: c.TTY,
}
copyContainerSecurityContext(&item, c.SecurityContext)
return item
}
func copyContainerSecurityContext(item *CommonContainerFields, sc *v1.SecurityContext) {
if sc != nil {
item.Privileged = sc.Privileged
item.RunAsUser = sc.RunAsUser
item.RunAsGroup = sc.RunAsGroup
item.RunAsNonRoot = sc.RunAsNonRoot
item.ReadOnlyRootFilesystem = sc.ReadOnlyRootFilesystem
item.AllowPrivilegeEscalation = sc.AllowPrivilegeEscalation
item.ProcMount = sc.ProcMount
if sc.Capabilities != nil {
item.CapabilitiesAdd = sc.Capabilities.Add
item.CapabilitiesDrop = sc.Capabilities.Drop
}
if sc.SeccompProfile != nil {
item.SeccompProfileType = sc.SeccompProfile.Type
item.SeccompProfileLocalhostProfile = sc.SeccompProfile.LocalhostProfile
}
if sc.SELinuxOptions != nil {
item.SELinuxOptionsLevel = sc.SELinuxOptions.Level
item.SELinuxOptionsRole = sc.SELinuxOptions.Role
item.SELinuxOptionsType = sc.SELinuxOptions.Type
item.SELinuxOptionsUser = sc.SELinuxOptions.User
}
if sc.WindowsOptions != nil {
item.WindowsOptionsRunAsUserName = sc.WindowsOptions.RunAsUserName
item.WindowsOptionsGMSACredentialSpec = sc.WindowsOptions.GMSACredentialSpec
item.WindowsOptionsGMSACredentialSpecName = sc.WindowsOptions.GMSACredentialSpecName
}
}
}
// CommonVolumeFields contains flattened fields from volume specification.
type CommonVolumeFields struct {
VolumeType string
FSType *string
ReadOnly *bool
SecretName string
HostPathPath string
HostPathType *v1.HostPathType
EmptyDirMedium v1.StorageMedium
EmptyDirSizeLimit string
GCEPersistentDiskPDName string
GCEPersistentDiskPartition int32
AWSElasticBlockStoreVolumeID string
AWSElasticBlockStorePartition int32
GitRepoRepository string
GitRepoRevision string
GitRepoDirectory string
SecretItems []v1.KeyToPath
SecretDefaultMode *int32
SecretOptional *bool
NFSServer string
NFSPath string
ISCSITargetPortal string
ISCSIIqn string
ISCSILun int32
ISCSIInterface string
ISCSIPortals []string
ISCSIDiscoveryCHAPAuth bool
ISCSISessionCHAPAuth bool
ISCSIInitiatorName *string
GlusterfsEndpointsName string
GlusterfsPath string
PersistentVolumeClaimName string
RBDCephMonitors []string
RBDImage string
RBDPool string
RBDRadosUser string
RBDKeyring string
FlexVolumeDriver string
FlexVolumeOptions map[string]string
CinderVolumeID string
CephFSMonitors []string
CephFSPath string
CephFSUser string
CephFSSecretFile string
FlockerDatasetName string
FlockerDatasetUUID string
DownwardAPIItems []v1.DownwardAPIVolumeFile
DownwardAPIDefaultMode *int32
FCTargetWWNs []string
FCLun *int32
FcWWIDs []string
AzureFileShareName string
ConfigMapName string
ConfigMapItems []v1.KeyToPath
ConfigMapDefaultMode *int32
ConfigMapOptional *bool
VsphereVolumeVolumePath string
VsphereVolumeStoragePolicyName string
VsphereVolumeStoragePolicyID string
QuobyteRegistry string
QuobyteVolume string
QuobyteUser string
QuobyteGroup string
QuobyteTenant string
AzureDiskDiskName string
AzureDiskDataDiskURI string
AzureDiskCachingMode *v1.AzureDataDiskCachingMode
AzureDiskKind *v1.AzureDataDiskKind
PhotonPersistentDiskPdID string
ProjectedSources []v1.VolumeProjection
ProjectedDefaultMode *int32
PortworxVolumeID string
ScaleIOGateway string
ScaleIOSystem string
ScaleIOSSLEnabled bool
ScaleIOProtectionDomain string
ScaleIOStoragePool string
ScaleIOStorageMode string
ScaleIOVolumeName string
StorageOSVolumeName string
StorageOSVolumeNamespace string
CSIDriver string
CSIVolumeAttributes map[string]string
EphemeralVolumeClaimTemplate *v1.PersistentVolumeClaimTemplate
}
// GetCommonVolumeFields converts volume specification to CommonVolumeFields.
// This flattens most of the embedded structures like AWSElasticBlockStore, AzureDisk, etc.
func GetCommonVolumeFields(from v1.Volume) CommonVolumeFields {
to := CommonVolumeFields{}
if from.AWSElasticBlockStore != nil {
to.VolumeType = "aws_elastic_block_store"
to.AWSElasticBlockStoreVolumeID = from.AWSElasticBlockStore.VolumeID
to.AWSElasticBlockStorePartition = from.AWSElasticBlockStore.Partition
to.FSType = &from.AWSElasticBlockStore.FSType
to.ReadOnly = &from.AWSElasticBlockStore.ReadOnly
}
if from.AzureDisk != nil {
to.VolumeType = "azure_disk"
to.AzureDiskCachingMode = from.AzureDisk.CachingMode
to.AzureDiskDataDiskURI = from.AzureDisk.DataDiskURI
to.AzureDiskDiskName = from.AzureDisk.DiskName
to.AzureDiskKind = from.AzureDisk.Kind
to.FSType = from.AzureDisk.FSType
to.ReadOnly = from.AzureDisk.ReadOnly
}
if from.AzureFile != nil {
to.VolumeType = "azure_file"
to.AzureFileShareName = from.AzureFile.ShareName
to.SecretName = from.AzureFile.SecretName
to.ReadOnly = &from.AzureFile.ReadOnly
}
if from.CSI != nil {
to.VolumeType = "csi"
to.CSIDriver = from.CSI.Driver
to.CSIVolumeAttributes = from.CSI.VolumeAttributes
to.FSType = from.CSI.FSType
to.ReadOnly = from.CSI.ReadOnly
if from.CSI.NodePublishSecretRef != nil {
to.SecretName = from.CSI.NodePublishSecretRef.Name
}
}
if from.CephFS != nil {
to.VolumeType = "ceph_fs"
to.CephFSMonitors = from.CephFS.Monitors
to.CephFSPath = from.CephFS.Path
to.CephFSSecretFile = from.CephFS.SecretFile
to.CephFSUser = from.CephFS.User
to.ReadOnly = &from.CephFS.ReadOnly
if from.CephFS.SecretRef != nil {
to.SecretName = from.CephFS.SecretRef.Name
}
}
if from.Cinder != nil {
to.VolumeType = "cinder"
to.CinderVolumeID = from.Cinder.VolumeID
to.FSType = &from.Cinder.FSType
to.ReadOnly = &from.Cinder.ReadOnly
if from.Cinder.SecretRef != nil {
to.SecretName = from.Cinder.SecretRef.Name
}
}
if from.ConfigMap != nil {
to.VolumeType = "config_map"
to.ConfigMapDefaultMode = from.ConfigMap.DefaultMode
to.ConfigMapItems = from.ConfigMap.Items
to.ConfigMapName = from.ConfigMap.Name
to.ConfigMapOptional = from.ConfigMap.Optional
}
if from.DownwardAPI != nil {
to.VolumeType = "downward_api"
to.DownwardAPIDefaultMode = from.DownwardAPI.DefaultMode
to.DownwardAPIItems = from.DownwardAPI.Items
}
if from.EmptyDir != nil {
to.VolumeType = "empty_dir"
to.EmptyDirMedium = from.EmptyDir.Medium
to.EmptyDirSizeLimit = from.EmptyDir.SizeLimit.String()
}
if from.Ephemeral != nil {
to.VolumeType = "ephemeral"
to.EphemeralVolumeClaimTemplate = from.Ephemeral.VolumeClaimTemplate
}
if from.FC != nil {
to.VolumeType = "fc"
to.FCLun = from.FC.Lun
to.FCTargetWWNs = from.FC.TargetWWNs
to.FcWWIDs = from.FC.WWIDs
to.FSType = &from.FC.FSType
to.ReadOnly = &from.FC.ReadOnly
}
if from.FlexVolume != nil {
to.VolumeType = "flex_volume"
to.FlexVolumeDriver = from.FlexVolume.Driver
to.FlexVolumeOptions = from.FlexVolume.Options
to.FSType = &from.FlexVolume.FSType
to.ReadOnly = &from.FlexVolume.ReadOnly
if from.FlexVolume.SecretRef != nil {
to.SecretName = from.FlexVolume.SecretRef.Name
}
}
if from.Flocker != nil {
to.VolumeType = "flocker"
to.FlockerDatasetName = from.Flocker.DatasetName
to.FlockerDatasetUUID = from.Flocker.DatasetUUID
}
if from.GCEPersistentDisk != nil {
to.VolumeType = "gce_persistent_disk"
to.GCEPersistentDiskPDName = from.GCEPersistentDisk.PDName
to.GCEPersistentDiskPartition = from.GCEPersistentDisk.Partition
to.FSType = &from.GCEPersistentDisk.FSType
to.ReadOnly = &from.GCEPersistentDisk.ReadOnly
}
if from.GitRepo != nil {
to.VolumeType = "git_repo"
to.GitRepoDirectory = from.GitRepo.Directory
to.GitRepoRepository = from.GitRepo.Repository
to.GitRepoRevision = from.GitRepo.Revision
}
if from.Glusterfs != nil {
to.VolumeType = "gluster_fs"
to.GlusterfsPath = from.Glusterfs.Path
to.GlusterfsEndpointsName = from.Glusterfs.EndpointsName
to.ReadOnly = &from.Glusterfs.ReadOnly
}
if from.HostPath != nil {
to.VolumeType = "host_path"
to.HostPathPath = from.HostPath.Path
to.HostPathType = from.HostPath.Type
}
if from.ISCSI != nil {
to.VolumeType = "iscsci"
to.ISCSITargetPortal = from.ISCSI.TargetPortal
to.ISCSIIqn = from.ISCSI.IQN
to.ISCSILun = from.ISCSI.Lun
to.ISCSIInterface = from.ISCSI.ISCSIInterface
to.ISCSIPortals = from.ISCSI.Portals
to.ISCSIDiscoveryCHAPAuth = from.ISCSI.DiscoveryCHAPAuth
to.ISCSISessionCHAPAuth = from.ISCSI.SessionCHAPAuth
to.ISCSIInitiatorName = from.ISCSI.InitiatorName
to.FSType = &from.ISCSI.FSType
to.ReadOnly = &from.ISCSI.ReadOnly
if from.ISCSI.SecretRef != nil {
to.SecretName = from.ISCSI.SecretRef.Name
}
}
if from.NFS != nil {
to.VolumeType = "nfs"
to.NFSPath = from.NFS.Path
to.NFSServer = from.NFS.Server
to.ReadOnly = &from.NFS.ReadOnly
}
if from.PersistentVolumeClaim != nil {
to.VolumeType = "persistent_volume_claim"
to.PersistentVolumeClaimName = from.PersistentVolumeClaim.ClaimName
to.ReadOnly = &from.PersistentVolumeClaim.ReadOnly
}
if from.PhotonPersistentDisk != nil {
to.VolumeType = "photon_persistent_disk"
to.PhotonPersistentDiskPdID = from.PhotonPersistentDisk.PdID
to.FSType = &from.PhotonPersistentDisk.FSType
}
if from.PortworxVolume != nil {
to.VolumeType = "portworx_volume"
to.PortworxVolumeID = from.PortworxVolume.VolumeID
to.FSType = &from.PortworxVolume.FSType
to.ReadOnly = &from.PortworxVolume.ReadOnly
}
if from.Projected != nil {
to.VolumeType = "projected"
to.ProjectedDefaultMode = from.Projected.DefaultMode
to.ProjectedSources = from.Projected.Sources
}
if from.Quobyte != nil {
to.VolumeType = "quobyte"
to.QuobyteGroup = from.Quobyte.Group
to.QuobyteRegistry = from.Quobyte.Registry
to.QuobyteTenant = from.Quobyte.Tenant
to.QuobyteUser = from.Quobyte.User
to.QuobyteVolume = from.Quobyte.Volume
to.ReadOnly = &from.Quobyte.ReadOnly
}
if from.RBD != nil {
to.VolumeType = "rbd"
to.RBDCephMonitors = from.RBD.CephMonitors
to.RBDImage = from.RBD.RBDImage
to.RBDPool = from.RBD.RBDPool
to.RBDRadosUser = from.RBD.RadosUser
to.RBDKeyring = from.RBD.Keyring
to.FSType = &from.RBD.FSType
to.ReadOnly = &from.RBD.ReadOnly
if from.RBD.SecretRef != nil {
to.SecretName = from.RBD.SecretRef.Name
}
}
if from.ScaleIO != nil {
to.VolumeType = "scaleio"
to.ScaleIOGateway = from.ScaleIO.Gateway
to.ScaleIOSystem = from.ScaleIO.System
to.ScaleIOSSLEnabled = from.ScaleIO.SSLEnabled
to.ScaleIOProtectionDomain = from.ScaleIO.ProtectionDomain
to.ScaleIOStoragePool = from.ScaleIO.StoragePool
to.ScaleIOStorageMode = from.ScaleIO.StorageMode
to.ScaleIOVolumeName = from.ScaleIO.VolumeName
to.FSType = &from.ScaleIO.FSType
to.ReadOnly = &from.ScaleIO.ReadOnly
if from.ScaleIO.SecretRef != nil {
to.SecretName = from.ScaleIO.SecretRef.Name
}
}
if from.Secret != nil {
to.VolumeType = "secret"
to.SecretName = from.Secret.SecretName
to.SecretItems = from.Secret.Items
to.SecretDefaultMode = from.Secret.DefaultMode
to.SecretOptional = from.Secret.Optional
}
if from.StorageOS != nil {
to.VolumeType = "storage_os"
to.StorageOSVolumeName = from.StorageOS.VolumeName
to.StorageOSVolumeNamespace = from.StorageOS.VolumeNamespace
to.FSType = &from.StorageOS.FSType
to.ReadOnly = &from.StorageOS.ReadOnly
if from.StorageOS.SecretRef != nil {
to.SecretName = from.StorageOS.SecretRef.Name
}
}
if from.VsphereVolume != nil {
to.VolumeType = "vsphere_volume"
to.VsphereVolumeStoragePolicyID = from.VsphereVolume.StoragePolicyID
to.VsphereVolumeStoragePolicyName = from.VsphereVolume.StoragePolicyName
to.VsphereVolumeVolumePath = from.VsphereVolume.VolumePath
to.FSType = &from.VsphereVolume.FSType
}
return to
}

View File

@ -0,0 +1,428 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package k8s
import (
"testing"
"github.com/stretchr/testify/assert"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
)
func TestGetCommonFields(t *testing.T) {
meta := metav1.ObjectMeta{
Name: "n123",
GenerateName: "g123",
Namespace: "kube-system",
SelfLink: "/",
UID: types.UID("u123"),
ResourceVersion: "r123",
Generation: 1,
CreationTimestamp: metav1.Time{},
DeletionGracePeriodSeconds: nil,
Labels: map[string]string{"a": "b"},
ClusterName: "",
}
assert.Equal(t, GetCommonFields(meta), CommonFields{
UID: meta.UID,
Name: meta.Name,
ClusterName: "cluster-name",
ClusterUID: types.UID("uid"),
CreationTimestamp: meta.CreationTimestamp,
Labels: meta.Labels,
Annotations: meta.Annotations,
}, "Common fields should match")
}
func TestGetNamespaceCommonFields(t *testing.T) {
meta := metav1.ObjectMeta{
Name: "n123",
GenerateName: "g123",
Namespace: "kube-system",
SelfLink: "/",
UID: types.UID("u123"),
ResourceVersion: "r123",
Generation: 1,
CreationTimestamp: metav1.Time{},
DeletionGracePeriodSeconds: nil,
Annotations: map[string]string{"a": "b"},
ClusterName: "",
}
assert.Equal(t, GetCommonNamespacedFields(meta), CommonNamespacedFields{
UID: meta.UID,
Name: meta.Name,
Namespace: meta.Namespace,
ClusterName: "cluster-name",
ClusterUID: types.UID("uid"),
CreationTimestamp: meta.CreationTimestamp,
Labels: meta.Labels,
Annotations: meta.Annotations,
}, "Common namespace fields should match")
}
func TestGetCommonPodFields(t *testing.T) {
i32 := int32(456)
i64 := int64(123)
b := bool(true)
s := string("s123")
pod := v1.PodSpec{
RestartPolicy: v1.RestartPolicyAlways,
TerminationGracePeriodSeconds: &i64,
ActiveDeadlineSeconds: &i64,
DNSPolicy: v1.DNSClusterFirst,
ServiceAccountName: "s123",
AutomountServiceAccountToken: &b,
NodeSelector: make(map[string]string),
NodeName: "n123",
HostNetwork: true,
HostPID: true,
HostIPC: true,
ShareProcessNamespace: &b,
ImagePullSecrets: make([]v1.LocalObjectReference, 3),
Hostname: "h123",
Subdomain: "sub123",
Affinity: &v1.Affinity{NodeAffinity: &v1.NodeAffinity{RequiredDuringSchedulingIgnoredDuringExecution: &v1.NodeSelector{}}},
SchedulerName: "sn123",
Tolerations: make([]v1.Toleration, 2),
HostAliases: make([]v1.HostAlias, 1),
PriorityClassName: "p123",
Priority: &i32,
ReadinessGates: []v1.PodReadinessGate{},
RuntimeClassName: &s,
EnableServiceLinks: &b,
PreemptionPolicy: nil,
Overhead: make(v1.ResourceList),
TopologySpreadConstraints: make([]v1.TopologySpreadConstraint, 4),
SetHostnameAsFQDN: &b,
DNSConfig: &v1.PodDNSConfig{
Nameservers: make([]string, 1),
Searches: make([]string, 2),
Options: make([]v1.PodDNSConfigOption, 3),
},
SecurityContext: &v1.PodSecurityContext{
RunAsUser: &i64,
RunAsGroup: &i64,
RunAsNonRoot: &b,
FSGroup: &i64,
FSGroupChangePolicy: (*v1.PodFSGroupChangePolicy)(&s),
Sysctls: []v1.Sysctl{{Name: "n1", Value: "v1"}},
SELinuxOptions: &v1.SELinuxOptions{User: "u123", Role: "r123", Type: "t123", Level: "l123"},
SupplementalGroups: make([]int64, 1),
SeccompProfile: &v1.SeccompProfile{Type: "t123"},
},
}
assert.Equal(t, GetCommonPodFields(pod), CommonPodFields{
PodSecurityContextFields: PodSecurityContextFields{
CommonSecurityContextFields: CommonSecurityContextFields{
SELinuxOptionsFields: SELinuxOptionsFields{
SELinuxOptionsUser: pod.SecurityContext.SELinuxOptions.User,
SELinuxOptionsRole: pod.SecurityContext.SELinuxOptions.Role,
SELinuxOptionsType: pod.SecurityContext.SELinuxOptions.Type,
SELinuxOptionsLevel: pod.SecurityContext.SELinuxOptions.Level,
},
WindowsOptionsFields: WindowsOptionsFields{
WindowsOptionsGMSACredentialSpecName: nil,
WindowsOptionsGMSACredentialSpec: nil,
WindowsOptionsRunAsUserName: nil,
},
SeccompProfileFields: SeccompProfileFields{
SeccompProfileType: pod.SecurityContext.SeccompProfile.Type,
SeccompProfileLocalhostProfile: pod.SecurityContext.SeccompProfile.LocalhostProfile,
},
RunAsUser: pod.SecurityContext.RunAsUser,
RunAsGroup: pod.SecurityContext.RunAsGroup,
RunAsNonRoot: pod.SecurityContext.RunAsNonRoot,
},
SupplementalGroups: pod.SecurityContext.SupplementalGroups,
FSGroup: pod.SecurityContext.FSGroup,
Sysctls: pod.SecurityContext.Sysctls,
FSGroupChangePolicy: pod.SecurityContext.FSGroupChangePolicy,
},
DNSConfigFields: DNSConfigFields{
DNSConfigNameservers: pod.DNSConfig.Nameservers,
DNSConfigSearches: pod.DNSConfig.Searches,
DNSConfigOptions: pod.DNSConfig.Options,
},
AffinityFields: AffinityFields{
NodeAffinity: pod.Affinity.NodeAffinity,
PodAffinity: pod.Affinity.PodAffinity,
PodAntiAffinity: pod.Affinity.PodAntiAffinity,
},
NodeSelector: pod.NodeSelector,
RestartPolicy: pod.RestartPolicy,
TerminationGracePeriodSeconds: pod.TerminationGracePeriodSeconds,
ActiveDeadlineSeconds: pod.ActiveDeadlineSeconds,
DNSPolicy: pod.DNSPolicy,
ServiceAccountName: pod.ServiceAccountName,
AutomountServiceAccountToken: pod.AutomountServiceAccountToken,
NodeName: pod.NodeName,
HostNetwork: pod.HostNetwork,
HostPID: pod.HostPID,
HostIPC: pod.HostIPC,
ShareProcessNamespace: pod.ShareProcessNamespace,
ImagePullSecrets: pod.ImagePullSecrets,
Hostname: pod.Hostname,
Subdomain: pod.Subdomain,
SchedulerName: pod.SchedulerName,
Tolerations: pod.Tolerations,
HostAliases: pod.HostAliases,
PriorityClassName: pod.PriorityClassName,
Priority: pod.Priority,
ReadinessGates: pod.ReadinessGates,
RuntimeClassName: pod.RuntimeClassName,
EnableServiceLinks: pod.EnableServiceLinks,
PreemptionPolicy: pod.PreemptionPolicy,
Overhead: pod.Overhead,
TopologySpreadConstraints: pod.TopologySpreadConstraints,
SetHostnameAsFQDN: pod.SetHostnameAsFQDN,
}, "Common pod fields should match")
}
func TestGetCommonContainerFields(t *testing.T) {
i64 := int64(456)
b := bool(true)
s := string("str123")
c := v1.Container{
Name: "n123",
Image: "i123",
Command: []string{"c123"},
Args: []string{"a1", "a2"},
WorkingDir: "w123",
Ports: make([]v1.ContainerPort, 1),
EnvFrom: []v1.EnvFromSource{{Prefix: "p123"}},
Env: []v1.EnvVar{{Name: "n1", Value: "v1"}},
Resources: v1.ResourceRequirements{Limits: v1.ResourceList{}},
VolumeMounts: make([]v1.VolumeMount, 2),
VolumeDevices: []v1.VolumeDevice{{Name: "vn1"}},
LivenessProbe: &v1.Probe{Handler: v1.Handler{Exec: &v1.ExecAction{Command: []string{"curl"}}}},
ReadinessProbe: &v1.Probe{},
StartupProbe: nil,
Lifecycle: &v1.Lifecycle{PostStart: &v1.Handler{Exec: &v1.ExecAction{Command: []string{"curl"}}}},
TerminationMessagePath: "t123",
TerminationMessagePolicy: v1.TerminationMessageFallbackToLogsOnError,
ImagePullPolicy: v1.PullAlways,
Stdin: true,
StdinOnce: false,
TTY: true,
SecurityContext: &v1.SecurityContext{
Capabilities: &v1.Capabilities{Add: []v1.Capability{"a"}, Drop: []v1.Capability{"b", "c"}},
Privileged: &b,
RunAsUser: &i64,
RunAsGroup: nil,
RunAsNonRoot: &b,
ReadOnlyRootFilesystem: nil,
AllowPrivilegeEscalation: &b,
ProcMount: nil,
SELinuxOptions: &v1.SELinuxOptions{
User: "u123",
Role: "r123",
Type: "t123",
Level: "",
},
SeccompProfile: &v1.SeccompProfile{
Type: v1.SeccompProfileType("abc"),
LocalhostProfile: &s,
},
WindowsOptions: nil,
},
}
assert.Equal(t, GetCommonContainerFields(c), CommonContainerFields{
SecurityContextFields: SecurityContextFields{
CommonSecurityContextFields: CommonSecurityContextFields{
SELinuxOptionsFields: SELinuxOptionsFields{
SELinuxOptionsUser: c.SecurityContext.SELinuxOptions.User,
SELinuxOptionsRole: c.SecurityContext.SELinuxOptions.Role,
SELinuxOptionsType: c.SecurityContext.SELinuxOptions.Type,
SELinuxOptionsLevel: c.SecurityContext.SELinuxOptions.Level,
},
WindowsOptionsFields: WindowsOptionsFields{
WindowsOptionsGMSACredentialSpecName: nil,
WindowsOptionsGMSACredentialSpec: nil,
WindowsOptionsRunAsUserName: nil,
},
SeccompProfileFields: SeccompProfileFields{
SeccompProfileType: c.SecurityContext.SeccompProfile.Type,
SeccompProfileLocalhostProfile: c.SecurityContext.SeccompProfile.LocalhostProfile,
},
RunAsUser: c.SecurityContext.RunAsUser,
RunAsGroup: c.SecurityContext.RunAsGroup,
RunAsNonRoot: c.SecurityContext.RunAsNonRoot,
},
CapabilitiesAdd: c.SecurityContext.Capabilities.Add,
CapabilitiesDrop: c.SecurityContext.Capabilities.Drop,
Privileged: c.SecurityContext.Privileged,
ReadOnlyRootFilesystem: c.SecurityContext.ReadOnlyRootFilesystem,
AllowPrivilegeEscalation: c.SecurityContext.AllowPrivilegeEscalation,
ProcMount: c.SecurityContext.ProcMount,
},
TargetContainerName: "",
Image: c.Image,
Command: c.Command,
Args: c.Args,
WorkingDir: c.WorkingDir,
Ports: c.Ports,
EnvFrom: c.EnvFrom,
Env: c.Env,
ResourceLimits: c.Resources.Limits,
ResourceRequests: c.Resources.Requests,
VolumeMounts: c.VolumeMounts,
VolumeDevices: c.VolumeDevices,
LivenessProbe: c.LivenessProbe,
ReadinessProbe: c.ReadinessProbe,
StartupProbe: c.StartupProbe,
Lifecycle: c.Lifecycle,
TerminationMessagePath: c.TerminationMessagePath,
TerminationMessagePolicy: c.TerminationMessagePolicy,
ImagePullPolicy: c.ImagePullPolicy,
Stdin: c.Stdin,
StdinOnce: c.StdinOnce,
TTY: c.TTY,
}, "Common container fields should match")
}
func TestGetCommonEphemeralContainerFields(t *testing.T) {
i64 := int64(456)
b := bool(true)
s := string("str123")
c := v1.EphemeralContainer{
TargetContainerName: "t123",
EphemeralContainerCommon: v1.EphemeralContainerCommon{
Name: "n123",
Image: "i123",
Command: []string{"c123"},
Args: []string{"a1", "a2"},
WorkingDir: "w123",
Ports: make([]v1.ContainerPort, 1),
EnvFrom: []v1.EnvFromSource{{Prefix: "p123"}},
Env: []v1.EnvVar{{Name: "n1", Value: "v1"}},
Resources: v1.ResourceRequirements{Limits: v1.ResourceList{}},
VolumeMounts: make([]v1.VolumeMount, 2),
VolumeDevices: []v1.VolumeDevice{{Name: "vn1"}},
LivenessProbe: &v1.Probe{Handler: v1.Handler{Exec: &v1.ExecAction{Command: []string{"curl"}}}},
ReadinessProbe: &v1.Probe{},
StartupProbe: nil,
Lifecycle: &v1.Lifecycle{PostStart: &v1.Handler{Exec: &v1.ExecAction{Command: []string{"curl"}}}},
TerminationMessagePath: "t123",
TerminationMessagePolicy: v1.TerminationMessageFallbackToLogsOnError,
ImagePullPolicy: v1.PullAlways,
Stdin: true,
StdinOnce: false,
TTY: true,
SecurityContext: &v1.SecurityContext{
Capabilities: &v1.Capabilities{Add: []v1.Capability{"a"}, Drop: []v1.Capability{"b", "c"}},
Privileged: &b,
RunAsUser: &i64,
RunAsGroup: nil,
RunAsNonRoot: &b,
ReadOnlyRootFilesystem: nil,
AllowPrivilegeEscalation: &b,
ProcMount: nil,
SELinuxOptions: &v1.SELinuxOptions{
User: "u123",
Role: "r123",
Type: "t123",
Level: "",
},
SeccompProfile: &v1.SeccompProfile{
Type: v1.SeccompProfileType("abc"),
LocalhostProfile: &s,
},
WindowsOptions: nil,
},
},
}
assert.Equal(t, GetCommonEphemeralContainerFields(c), CommonContainerFields{
SecurityContextFields: SecurityContextFields{
CommonSecurityContextFields: CommonSecurityContextFields{
SELinuxOptionsFields: SELinuxOptionsFields{
SELinuxOptionsUser: c.SecurityContext.SELinuxOptions.User,
SELinuxOptionsRole: c.SecurityContext.SELinuxOptions.Role,
SELinuxOptionsType: c.SecurityContext.SELinuxOptions.Type,
SELinuxOptionsLevel: c.SecurityContext.SELinuxOptions.Level,
},
WindowsOptionsFields: WindowsOptionsFields{
WindowsOptionsGMSACredentialSpecName: nil,
WindowsOptionsGMSACredentialSpec: nil,
WindowsOptionsRunAsUserName: nil,
},
SeccompProfileFields: SeccompProfileFields{
SeccompProfileType: c.SecurityContext.SeccompProfile.Type,
SeccompProfileLocalhostProfile: c.SecurityContext.SeccompProfile.LocalhostProfile,
},
RunAsUser: c.SecurityContext.RunAsUser,
RunAsGroup: c.SecurityContext.RunAsGroup,
RunAsNonRoot: c.SecurityContext.RunAsNonRoot,
},
CapabilitiesAdd: c.SecurityContext.Capabilities.Add,
CapabilitiesDrop: c.SecurityContext.Capabilities.Drop,
Privileged: c.SecurityContext.Privileged,
ReadOnlyRootFilesystem: c.SecurityContext.ReadOnlyRootFilesystem,
AllowPrivilegeEscalation: c.SecurityContext.AllowPrivilegeEscalation,
ProcMount: c.SecurityContext.ProcMount,
},
TargetContainerName: c.TargetContainerName,
Image: c.Image,
Command: c.Command,
Args: c.Args,
WorkingDir: c.WorkingDir,
Ports: c.Ports,
EnvFrom: c.EnvFrom,
Env: c.Env,
ResourceLimits: c.Resources.Limits,
ResourceRequests: c.Resources.Requests,
VolumeMounts: c.VolumeMounts,
VolumeDevices: c.VolumeDevices,
LivenessProbe: c.LivenessProbe,
ReadinessProbe: c.ReadinessProbe,
StartupProbe: c.StartupProbe,
Lifecycle: c.Lifecycle,
TerminationMessagePath: c.TerminationMessagePath,
TerminationMessagePolicy: c.TerminationMessagePolicy,
ImagePullPolicy: c.ImagePullPolicy,
Stdin: c.Stdin,
StdinOnce: c.StdinOnce,
TTY: c.TTY,
}, "Common ephemeral container fields should match")
}
func TestGetCommonVolumeFields(t *testing.T) {
v := v1.Volume{
VolumeSource: v1.VolumeSource{
HostPath: &v1.HostPathVolumeSource{
Path: "p123",
Type: nil,
},
},
}
assert.Equal(t, GetCommonVolumeFields(v), CommonVolumeFields{
VolumeType: "host_path",
HostPathPath: v.HostPath.Path,
HostPathType: v.HostPath.Type,
}, "Common volume HostPath fields should match")
v = v1.Volume{
VolumeSource: v1.VolumeSource{
GCEPersistentDisk: &v1.GCEPersistentDiskVolumeSource{
PDName: "p123",
FSType: "gce",
Partition: 123,
},
},
}
assert.Equal(t, GetCommonVolumeFields(v), CommonVolumeFields{
VolumeType: "gce_persistent_disk",
FSType: &v.GCEPersistentDisk.FSType,
ReadOnly: &v.GCEPersistentDisk.ReadOnly,
GCEPersistentDiskPDName: v.GCEPersistentDisk.PDName,
GCEPersistentDiskPartition: v.GCEPersistentDisk.Partition,
}, "Common volume GCE fields should match")
}

View File

@ -0,0 +1,64 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package core
import (
"context"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/Uptycs/kubequery/internal/k8s"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
)
type componentStatus struct {
ClusterName string
ClusterUID types.UID
Name string
v1.ComponentCondition
}
// ComponentStatusColumns returns kubernetes component status fields as Osquery table columns.
func ComponentStatusColumns() []table.ColumnDefinition {
return k8s.GetSchema(&componentStatus{})
}
// ComponentStatusesGenerate generates the kubernetes config maps as Osquery table data.
func ComponentStatusesGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
options := metav1.ListOptions{}
results := make([]map[string]string, 0)
for {
css, err := k8s.GetClient().CoreV1().ComponentStatuses().List(ctx, options)
if err != nil {
return nil, err
}
for _, cs := range css.Items {
for _, cc := range cs.Conditions {
item := &componentStatus{
ClusterName: k8s.GetClusterName(),
ClusterUID: k8s.GetClusterUID(),
Name: cs.ObjectMeta.Name,
ComponentCondition: cc,
}
results = append(results, k8s.ToMap(item))
}
}
if css.Continue == "" {
break
}
options.Continue = css.Continue
}
return results, nil
}

View File

@ -0,0 +1,46 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package core
import (
"context"
"testing"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/stretchr/testify/assert"
)
func TestComponentStatusesGenerate(t *testing.T) {
css, err := ComponentStatusesGenerate(context.TODO(), table.QueryContext{})
assert.Nil(t, err)
assert.Equal(t, []map[string]string{
{
"cluster_uid": "d7fd8e77-93de-4742-9037-5db9a01e966a",
"name": "controller-manager",
"message": "ok",
"status": "True",
"type": "Healthy",
},
{
"cluster_uid": "d7fd8e77-93de-4742-9037-5db9a01e966a",
"name": "etcd-0",
"message": "{\"health\":\"true\"}",
"status": "True",
"type": "Healthy",
},
{
"cluster_uid": "d7fd8e77-93de-4742-9037-5db9a01e966a",
"name": "scheduler",
"message": "ok",
"status": "True",
"type": "Healthy",
},
}, css)
}

View File

@ -0,0 +1,56 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package core
import (
"context"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/Uptycs/kubequery/internal/k8s"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type configmap struct {
k8s.CommonNamespacedFields
Immutable *bool
}
// ConfigMapColumns returns kubernetes config map fields as Osquery table columns.
func ConfigMapColumns() []table.ColumnDefinition {
return k8s.GetSchema(&configmap{})
}
// ConfigMapsGenerate generates the kubernetes config maps as Osquery table data.
func ConfigMapsGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
options := metav1.ListOptions{}
results := make([]map[string]string, 0)
for {
configmaps, err := k8s.GetClient().CoreV1().ConfigMaps(metav1.NamespaceAll).List(ctx, options)
if err != nil {
return nil, err
}
for _, c := range configmaps.Items {
item := &configmap{
CommonNamespacedFields: k8s.GetCommonNamespacedFields(c.ObjectMeta),
Immutable: c.Immutable,
}
results = append(results, k8s.ToMap(item))
}
if configmaps.Continue == "" {
break
}
options.Continue = configmaps.Continue
}
return results, nil
}

View File

@ -0,0 +1,32 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package core
import (
"context"
"testing"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/stretchr/testify/assert"
)
func TestConfigMapsGenerate(t *testing.T) {
cms, err := ConfigMapsGenerate(context.TODO(), table.QueryContext{})
assert.Nil(t, err)
assert.Equal(t, []map[string]string{
{
"cluster_uid": "d7fd8e77-93de-4742-9037-5db9a01e966a",
"creation_timestamp": "1611191331",
"name": "jaeger-operator-lock",
"namespace": "default",
"uid": "eec6944c-5c13-4e30-8326-1a82e1962e4d",
},
}, cms)
}

View File

@ -0,0 +1,59 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package core
import (
"context"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/Uptycs/kubequery/internal/k8s"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type endpointSubset struct {
k8s.CommonNamespacedFields
v1.EndpointSubset
}
// EndpointSubsetColumns returns kubernetes endpoint subset fields as Osquery table columns.
func EndpointSubsetColumns() []table.ColumnDefinition {
return k8s.GetSchema(&endpointSubset{})
}
// EndpointSubsetsGenerate generates the kubernetes endpoint subsets as Osquery table data.
func EndpointSubsetsGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
options := metav1.ListOptions{}
results := make([]map[string]string, 0)
for {
endpoints, err := k8s.GetClient().CoreV1().Endpoints(metav1.NamespaceAll).List(ctx, options)
if err != nil {
return nil, err
}
for _, e := range endpoints.Items {
for _, s := range e.Subsets {
item := &endpointSubset{
CommonNamespacedFields: k8s.GetCommonNamespacedFields(e.ObjectMeta),
EndpointSubset: s,
}
results = append(results, k8s.ToMap(item))
}
}
if endpoints.Continue == "" {
break
}
options.Continue = endpoints.Continue
}
return results, nil
}

View File

@ -0,0 +1,36 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package core
import (
"context"
"testing"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/stretchr/testify/assert"
)
func TestEndpointSubsetsGenerate(t *testing.T) {
ess, err := EndpointSubsetsGenerate(context.TODO(), table.QueryContext{})
assert.Nil(t, err)
assert.Equal(t, []map[string]string{
{
"addresses": "[{\"ip\":\"10.1.26.50\",\"nodeName\":\"seshu\",\"targetRef\":{\"kind\":\"Pod\",\"namespace\":\"default\",\"name\":\"jaeger-operator-5db4f9d996-pm7ld\",\"uid\":\"2271363b-ffc9-4f00-984c-e0a125ee2d7a\",\"resourceVersion\":\"451808\"}}]",
"annotations": "{\"endpoints.kubernetes.io/last-change-trigger-time\":\"2021-01-20T20:08:52-05:00\"}",
"cluster_uid": "d7fd8e77-93de-4742-9037-5db9a01e966a",
"creation_timestamp": "1611191332",
"labels": "{\"name\":\"jaeger-operator\"}",
"name": "jaeger-operator",
"namespace": "default",
"ports": "[{\"name\":\"metrics\",\"port\":8383,\"protocol\":\"TCP\"}]",
"uid": "013741da-d7a5-4a2d-8f4b-792ac6a40dd3",
},
}, ess)
}

View File

@ -0,0 +1,81 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package core
import (
"encoding/json"
"io/ioutil"
"path/filepath"
"github.com/Uptycs/kubequery/internal/k8s"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes/fake"
)
func loadTestResource(name string, v interface{}) {
path := filepath.Join("testdata", name)
data, err := ioutil.ReadFile(path)
if err != nil {
panic(err)
}
err = json.Unmarshal(data, v)
if err != nil {
panic(err)
}
}
func init() {
lr := &v1.LimitRange{
ObjectMeta: metav1.ObjectMeta{
Name: "lr1",
Namespace: "n123",
UID: types.UID("1234"),
Labels: map[string]string{"a": "b"},
},
Spec: v1.LimitRangeSpec{
Limits: []v1.LimitRangeItem{
{
Type: v1.LimitTypeContainer,
Max: v1.ResourceList{v1.ResourceCPU: resource.MustParse("0")},
Min: v1.ResourceList{v1.ResourceCPU: resource.MustParse("4")},
Default: v1.ResourceList{v1.ResourceCPU: resource.MustParse("3")},
DefaultRequest: v1.ResourceList{v1.ResourceCPU: resource.MustParse("2")},
MaxLimitRequestRatio: v1.ResourceList{v1.ResourceCPU: resource.MustParse("1")},
},
},
},
}
csl := &v1.ComponentStatusList{}
loadTestResource("component_status_test.json", csl)
cm := &v1.ConfigMap{}
loadTestResource("config_map_test.json", cm)
ep := &v1.Endpoints{}
loadTestResource("endpoint_subset_test.json", ep)
ns := &v1.NamespaceList{}
loadTestResource("namespaces_test.json", ns)
node := &v1.Node{}
loadTestResource("node_test.json", node)
pod := &v1.Pod{}
loadTestResource("pod_test.json", pod)
secret := &v1.Secret{}
loadTestResource("secret_test.json", secret)
sa := &v1.ServiceAccount{}
loadTestResource("service_account_test.json", sa)
services := &v1.Service{}
loadTestResource("services_test.json", services)
k8s.SetClient(fake.NewSimpleClientset(lr, csl, cm, ep, ns, node, pod, secret, sa, services),
types.UID("d7fd8e77-93de-4742-9037-5db9a01e966a"), "")
}

View File

@ -0,0 +1,59 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package core
import (
"context"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/Uptycs/kubequery/internal/k8s"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type limitRange struct {
k8s.CommonNamespacedFields
v1.LimitRangeItem
}
// LimitRangeColumns returns kubernetes limit range fields as Osquery table columns.
func LimitRangeColumns() []table.ColumnDefinition {
return k8s.GetSchema(&limitRange{})
}
// LimitRangesGenerate generates the kubernetes limit ranges as Osquery table data.
func LimitRangesGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
options := metav1.ListOptions{}
results := make([]map[string]string, 0)
for {
ranges, err := k8s.GetClient().CoreV1().LimitRanges(metav1.NamespaceAll).List(ctx, options)
if err != nil {
return nil, err
}
for _, r := range ranges.Items {
for _, i := range r.Spec.Limits {
item := &limitRange{
CommonNamespacedFields: k8s.GetCommonNamespacedFields(r.ObjectMeta),
LimitRangeItem: i,
}
results = append(results, k8s.ToMap(item))
}
}
if ranges.Continue == "" {
break
}
options.Continue = ranges.Continue
}
return results, nil
}

View File

@ -0,0 +1,39 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package core
import (
"context"
"testing"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/stretchr/testify/assert"
)
func TestLimitRangesGenerate(t *testing.T) {
js, err := LimitRangesGenerate(context.TODO(), table.QueryContext{})
assert.Nil(t, err)
assert.Equal(t, []map[string]string{
{
"cluster_uid": "d7fd8e77-93de-4742-9037-5db9a01e966a",
"creation_timestamp": "0",
"default": "{\"cpu\":\"3\"}",
"default_request": "{\"cpu\":\"2\"}",
"labels": "{\"a\":\"b\"}",
"max": "{\"cpu\":\"0\"}",
"max_limit_request_ratio": "{\"cpu\":\"1\"}",
"min": "{\"cpu\":\"4\"}",
"name": "lr1",
"namespace": "n123",
"type": "Container",
"uid": "1234",
},
}, js)
}

View File

@ -0,0 +1,57 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package core
import (
"context"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/Uptycs/kubequery/internal/k8s"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type namespace struct {
k8s.CommonFields
v1.NamespaceStatus
}
// NamespaceColumns returns kubernetes namespace fields as Osquery table columns.
func NamespaceColumns() []table.ColumnDefinition {
return k8s.GetSchema(&namespace{})
}
// NamespacesGenerate generates the kubernetes namespaces as Osquery table data.
func NamespacesGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
options := metav1.ListOptions{}
results := make([]map[string]string, 0)
for {
namespaces, err := k8s.GetClient().CoreV1().Namespaces().List(ctx, options)
if err != nil {
return nil, err
}
for _, n := range namespaces.Items {
item := &namespace{
CommonFields: k8s.GetCommonFields(n.ObjectMeta),
NamespaceStatus: n.Status,
}
results = append(results, k8s.ToMap(item))
}
if namespaces.Continue == "" {
break
}
options.Continue = namespaces.Continue
}
return results, nil
}

View File

@ -0,0 +1,78 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package core
import (
"context"
"testing"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/stretchr/testify/assert"
)
func TestNamespacesGenerate(t *testing.T) {
nss, err := NamespacesGenerate(context.TODO(), table.QueryContext{})
assert.Nil(t, err)
assert.Equal(t, []map[string]string{
{
"cluster_uid": "d7fd8e77-93de-4742-9037-5db9a01e966a",
"creation_timestamp": "1610476216",
"name": "default",
"phase": "Active",
"uid": "7b50dc9c-6149-4cac-a0d0-52bf0fa5356d",
},
{
"annotations": "{\"kubectl.kubernetes.io/last-applied-configuration\":\"{\\\"apiVersion\\\":\\\"v1\\\",\\\"kind\\\":\\\"Namespace\\\",\\\"metadata\\\":{\\\"annotations\\\":{},\\\"name\\\":\\\"ingress\\\"}}\\n\"}",
"cluster_uid": "d7fd8e77-93de-4742-9037-5db9a01e966a",
"creation_timestamp": "1611191047",
"name": "ingress",
"phase": "Active",
"uid": "7653c4b9-3df2-493e-ae28-5e3a777f7e76",
},
{
"annotations": "{\"kubectl.kubernetes.io/last-applied-configuration\":\"{\\\"apiVersion\\\":\\\"v1\\\",\\\"kind\\\":\\\"Namespace\\\",\\\"metadata\\\":{\\\"annotations\\\":{},\\\"labels\\\":{\\\"istio-injection\\\":\\\"disabled\\\"},\\\"name\\\":\\\"istio-system\\\"}}\\n\"}",
"cluster_uid": "d7fd8e77-93de-4742-9037-5db9a01e966a",
"creation_timestamp": "1611191143",
"labels": "{\"istio-injection\":\"disabled\"}",
"name": "istio-system",
"phase": "Active",
"uid": "7f931f07-f8d0-4198-bf16-e459914e1866",
},
{
"cluster_uid": "d7fd8e77-93de-4742-9037-5db9a01e966a",
"creation_timestamp": "1610476215",
"name": "kube-node-lease",
"phase": "Active",
"uid": "a8f303fd-0074-475f-935a-122cf8b6d1ad",
},
{
"cluster_uid": "d7fd8e77-93de-4742-9037-5db9a01e966a",
"creation_timestamp": "1610476215",
"name": "kube-public",
"phase": "Active",
"uid": "6c719dfa-3de8-477b-a650-8bf9e2f12ee0",
},
{
"cluster_uid": "d7fd8e77-93de-4742-9037-5db9a01e966a",
"creation_timestamp": "1610476215",
"name": "kube-system",
"phase": "Active",
"uid": "ebca5546-b939-4765-bf3d-869ac644ea0f",
},
{
"annotations": "{\"kubectl.kubernetes.io/last-applied-configuration\":\"{\\\"apiVersion\\\":\\\"v1\\\",\\\"kind\\\":\\\"Namespace\\\",\\\"metadata\\\":{\\\"annotations\\\":{},\\\"name\\\":\\\"monitoring\\\"}}\\n\"}",
"cluster_uid": "d7fd8e77-93de-4742-9037-5db9a01e966a",
"creation_timestamp": "1611191449",
"name": "monitoring",
"phase": "Active",
"uid": "afb98a87-39bb-4c8f-b0dd-8ea3683ba745",
},
}, nss)
}

View File

@ -0,0 +1,59 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package core
import (
"context"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/Uptycs/kubequery/internal/k8s"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type node struct {
k8s.CommonFields
v1.NodeSpec
v1.NodeStatus
}
// NodeColumns returns kubernetes node fields as Osquery table columns.
func NodeColumns() []table.ColumnDefinition {
return k8s.GetSchema(&node{})
}
// NodesGenerate generates the kubernetes nodes as Osquery table data.
func NodesGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
options := metav1.ListOptions{}
results := make([]map[string]string, 0)
for {
nodes, err := k8s.GetClient().CoreV1().Nodes().List(ctx, options)
if err != nil {
return nil, err
}
for _, n := range nodes.Items {
item := &node{
CommonFields: k8s.GetCommonFields(n.ObjectMeta),
NodeSpec: n.Spec,
NodeStatus: n.Status,
}
results = append(results, k8s.ToMap(item))
}
if nodes.Continue == "" {
break
}
options.Continue = nodes.Continue
}
return results, nil
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,330 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package core
import (
"context"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/Uptycs/kubequery/internal/k8s"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type persistentVolume struct {
k8s.CommonFields
Capacity v1.ResourceList
AccessModes []v1.PersistentVolumeAccessMode
ClaimRef *v1.ObjectReference
PersistentVolumeReclaimPolicy v1.PersistentVolumeReclaimPolicy
StorageClassName string
MountOptions []string
VolumeMode *v1.PersistentVolumeMode
NodeAffinity *v1.VolumeNodeAffinity
StatusPhase v1.PersistentVolumePhase
StatusMessage string
StatusReason string
VolumeType string
FSType *string
ReadOnly *bool
SecretName string
HostPathPath string
HostPathType *v1.HostPathType
GCEPersistentDiskPDName string
GCEPersistentDiskPartition int32
AWSElasticBlockStoreVolumeID string
AWSElasticBlockStorePartition int32
NFSServer string
NFSPath string
ISCSITargetPortal string
ISCSIIqn string
ISCSILun int32
ISCSIInterface string
ISCSIPortals []string
ISCSIDiscoveryCHAPAuth bool
ISCSISessionCHAPAuth bool
ISCSIInitiatorName *string
LocalPath string
GlusterfsEndpointsName string
GlusterfsPath string
RBDCephMonitors []string
RBDImage string
RBDPool string
RBDRadosUser string
RBDKeyring string
FlexVolumeDriver string
FlexVolumeOptions map[string]string
CinderVolumeID string
CephFSMonitors []string
CephFSPath string
CephFSUser string
CephFSSecretFile string
FlockerDatasetName string
FlockerDatasetUUID string
FCTargetWWNs []string
FCLun *int32
FcWWIDs []string
AzureFileShareName string
VsphereVolumeVolumePath string
VsphereVolumeStoragePolicyName string
VsphereVolumeStoragePolicyID string
QuobyteRegistry string
QuobyteVolume string
QuobyteUser string
QuobyteGroup string
QuobyteTenant string
AzureDiskDiskName string
AzureDiskDataDiskURI string
AzureDiskCachingMode *v1.AzureDataDiskCachingMode
AzureDiskKind *v1.AzureDataDiskKind
PhotonPersistentDiskPdID string
PortworxVolumeID string
ScaleIOGateway string
ScaleIOSystem string
ScaleIOSSLEnabled bool
ScaleIOProtectionDomain string
ScaleIOStoragePool string
ScaleIOStorageMode string
ScaleIOVolumeName string
StorageOSVolumeName string
StorageOSVolumeNamespace string
CSIDriver string
CSIVolumeAttributes map[string]string
}
// PersistentVolumeColumns returns kubernetes persistent volume fields as Osquery table columns.
func PersistentVolumeColumns() []table.ColumnDefinition {
return k8s.GetSchema(&persistentVolume{})
}
// PersistentVolumesGenerate generates the kubernetes persistent volumes as Osquery table data.
func PersistentVolumesGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
options := metav1.ListOptions{}
results := make([]map[string]string, 0)
for {
pvs, err := k8s.GetClient().CoreV1().PersistentVolumes().List(ctx, options)
if err != nil {
return nil, err
}
for _, pv := range pvs.Items {
item := &persistentVolume{
CommonFields: k8s.GetCommonFields(pv.ObjectMeta),
Capacity: pv.Spec.Capacity,
AccessModes: pv.Spec.AccessModes,
ClaimRef: pv.Spec.ClaimRef,
PersistentVolumeReclaimPolicy: pv.Spec.PersistentVolumeReclaimPolicy,
StorageClassName: pv.Spec.StorageClassName,
MountOptions: pv.Spec.MountOptions,
VolumeMode: pv.Spec.VolumeMode,
NodeAffinity: pv.Spec.NodeAffinity,
StatusPhase: pv.Status.Phase,
StatusMessage: pv.Status.Message,
StatusReason: pv.Status.Reason,
}
if pv.Spec.AWSElasticBlockStore != nil {
item.VolumeType = "aws_elastic_block_store"
item.AWSElasticBlockStoreVolumeID = pv.Spec.AWSElasticBlockStore.VolumeID
item.AWSElasticBlockStorePartition = pv.Spec.AWSElasticBlockStore.Partition
item.FSType = &pv.Spec.AWSElasticBlockStore.FSType
item.ReadOnly = &pv.Spec.AWSElasticBlockStore.ReadOnly
}
if pv.Spec.AzureDisk != nil {
item.VolumeType = "azure_disk"
item.AzureDiskCachingMode = pv.Spec.AzureDisk.CachingMode
item.AzureDiskDataDiskURI = pv.Spec.AzureDisk.DataDiskURI
item.AzureDiskDiskName = pv.Spec.AzureDisk.DiskName
item.AzureDiskKind = pv.Spec.AzureDisk.Kind
item.FSType = pv.Spec.AzureDisk.FSType
item.ReadOnly = pv.Spec.AzureDisk.ReadOnly
}
if pv.Spec.AzureFile != nil {
item.VolumeType = "azure_file"
item.AzureFileShareName = pv.Spec.AzureFile.ShareName
item.SecretName = pv.Spec.AzureFile.SecretName
item.ReadOnly = &pv.Spec.AzureFile.ReadOnly
}
if pv.Spec.CSI != nil {
item.VolumeType = "csi"
item.CSIDriver = pv.Spec.CSI.Driver
item.CSIVolumeAttributes = pv.Spec.CSI.VolumeAttributes
item.FSType = &pv.Spec.CSI.FSType
item.ReadOnly = &pv.Spec.CSI.ReadOnly
if pv.Spec.CSI.NodePublishSecretRef != nil {
item.SecretName = pv.Spec.CSI.NodePublishSecretRef.Name
}
}
if pv.Spec.CephFS != nil {
item.VolumeType = "ceph_fs"
item.CephFSMonitors = pv.Spec.CephFS.Monitors
item.CephFSPath = pv.Spec.CephFS.Path
item.CephFSSecretFile = pv.Spec.CephFS.SecretFile
item.CephFSUser = pv.Spec.CephFS.User
item.ReadOnly = &pv.Spec.CephFS.ReadOnly
if pv.Spec.CephFS.SecretRef != nil {
item.SecretName = pv.Spec.CephFS.SecretRef.Name
}
}
if pv.Spec.Cinder != nil {
item.VolumeType = "cinder"
item.CinderVolumeID = pv.Spec.Cinder.VolumeID
item.FSType = &pv.Spec.Cinder.FSType
item.ReadOnly = &pv.Spec.Cinder.ReadOnly
if pv.Spec.Cinder.SecretRef != nil {
item.SecretName = pv.Spec.Cinder.SecretRef.Name
}
}
if pv.Spec.FC != nil {
item.VolumeType = "fc"
item.FCLun = pv.Spec.FC.Lun
item.FCTargetWWNs = pv.Spec.FC.TargetWWNs
item.FcWWIDs = pv.Spec.FC.WWIDs
item.FSType = &pv.Spec.FC.FSType
item.ReadOnly = &pv.Spec.FC.ReadOnly
}
if pv.Spec.FlexVolume != nil {
item.VolumeType = "flex_volume"
item.FlexVolumeDriver = pv.Spec.FlexVolume.Driver
item.FlexVolumeOptions = pv.Spec.FlexVolume.Options
item.FSType = &pv.Spec.FlexVolume.FSType
item.ReadOnly = &pv.Spec.FlexVolume.ReadOnly
if pv.Spec.FlexVolume.SecretRef != nil {
item.SecretName = pv.Spec.FlexVolume.SecretRef.Name
}
}
if pv.Spec.Flocker != nil {
item.VolumeType = "flocker"
item.FlockerDatasetName = pv.Spec.Flocker.DatasetName
item.FlockerDatasetUUID = pv.Spec.Flocker.DatasetUUID
}
if pv.Spec.GCEPersistentDisk != nil {
item.VolumeType = "gce_persistent_disk"
item.GCEPersistentDiskPDName = pv.Spec.GCEPersistentDisk.PDName
item.GCEPersistentDiskPartition = pv.Spec.GCEPersistentDisk.Partition
item.FSType = &pv.Spec.GCEPersistentDisk.FSType
item.ReadOnly = &pv.Spec.GCEPersistentDisk.ReadOnly
}
if pv.Spec.Glusterfs != nil {
item.VolumeType = "gluster_fs"
item.GlusterfsPath = pv.Spec.Glusterfs.Path
item.GlusterfsEndpointsName = pv.Spec.Glusterfs.EndpointsName
item.ReadOnly = &pv.Spec.Glusterfs.ReadOnly
}
if pv.Spec.HostPath != nil {
item.VolumeType = "host_path"
item.HostPathPath = pv.Spec.HostPath.Path
item.HostPathType = pv.Spec.HostPath.Type
}
if pv.Spec.ISCSI != nil {
item.VolumeType = "iscsci"
item.ISCSITargetPortal = pv.Spec.ISCSI.TargetPortal
item.ISCSIIqn = pv.Spec.ISCSI.IQN
item.ISCSILun = pv.Spec.ISCSI.Lun
item.ISCSIInterface = pv.Spec.ISCSI.ISCSIInterface
item.ISCSIPortals = pv.Spec.ISCSI.Portals
item.ISCSIDiscoveryCHAPAuth = pv.Spec.ISCSI.DiscoveryCHAPAuth
item.ISCSISessionCHAPAuth = pv.Spec.ISCSI.SessionCHAPAuth
item.ISCSIInitiatorName = pv.Spec.ISCSI.InitiatorName
item.FSType = &pv.Spec.ISCSI.FSType
item.ReadOnly = &pv.Spec.ISCSI.ReadOnly
if pv.Spec.ISCSI.SecretRef != nil {
item.SecretName = pv.Spec.ISCSI.SecretRef.Name
}
}
if pv.Spec.Local != nil {
item.LocalPath = pv.Spec.Local.Path
item.FSType = pv.Spec.Local.FSType
}
if pv.Spec.NFS != nil {
item.VolumeType = "nfs"
item.NFSPath = pv.Spec.NFS.Path
item.NFSServer = pv.Spec.NFS.Server
item.ReadOnly = &pv.Spec.NFS.ReadOnly
}
if pv.Spec.PhotonPersistentDisk != nil {
item.VolumeType = "photon_persistent_disk"
item.PhotonPersistentDiskPdID = pv.Spec.PhotonPersistentDisk.PdID
item.FSType = &pv.Spec.PhotonPersistentDisk.FSType
}
if pv.Spec.PortworxVolume != nil {
item.VolumeType = "portworx_volume"
item.PortworxVolumeID = pv.Spec.PortworxVolume.VolumeID
item.FSType = &pv.Spec.PortworxVolume.FSType
item.ReadOnly = &pv.Spec.PortworxVolume.ReadOnly
}
if pv.Spec.Quobyte != nil {
item.VolumeType = "quobyte"
item.QuobyteGroup = pv.Spec.Quobyte.Group
item.QuobyteRegistry = pv.Spec.Quobyte.Registry
item.QuobyteTenant = pv.Spec.Quobyte.Tenant
item.QuobyteUser = pv.Spec.Quobyte.User
item.QuobyteVolume = pv.Spec.Quobyte.Volume
item.ReadOnly = &pv.Spec.Quobyte.ReadOnly
}
if pv.Spec.RBD != nil {
item.VolumeType = "rbd"
item.RBDCephMonitors = pv.Spec.RBD.CephMonitors
item.RBDImage = pv.Spec.RBD.RBDImage
item.RBDPool = pv.Spec.RBD.RBDPool
item.RBDRadosUser = pv.Spec.RBD.RadosUser
item.RBDKeyring = pv.Spec.RBD.Keyring
item.FSType = &pv.Spec.RBD.FSType
item.ReadOnly = &pv.Spec.RBD.ReadOnly
if pv.Spec.RBD.SecretRef != nil {
item.SecretName = pv.Spec.RBD.SecretRef.Name
}
}
if pv.Spec.ScaleIO != nil {
item.VolumeType = "scaleio"
item.ScaleIOGateway = pv.Spec.ScaleIO.Gateway
item.ScaleIOSystem = pv.Spec.ScaleIO.System
item.ScaleIOSSLEnabled = pv.Spec.ScaleIO.SSLEnabled
item.ScaleIOProtectionDomain = pv.Spec.ScaleIO.ProtectionDomain
item.ScaleIOStoragePool = pv.Spec.ScaleIO.StoragePool
item.ScaleIOStorageMode = pv.Spec.ScaleIO.StorageMode
item.ScaleIOVolumeName = pv.Spec.ScaleIO.VolumeName
item.FSType = &pv.Spec.ScaleIO.FSType
item.ReadOnly = &pv.Spec.ScaleIO.ReadOnly
if pv.Spec.ScaleIO.SecretRef != nil {
item.SecretName = pv.Spec.ScaleIO.SecretRef.Name
}
}
if pv.Spec.StorageOS != nil {
item.VolumeType = "storage_os"
item.StorageOSVolumeName = pv.Spec.StorageOS.VolumeName
item.StorageOSVolumeNamespace = pv.Spec.StorageOS.VolumeNamespace
item.FSType = &pv.Spec.StorageOS.FSType
item.ReadOnly = &pv.Spec.StorageOS.ReadOnly
if pv.Spec.StorageOS.SecretRef != nil {
item.SecretName = pv.Spec.StorageOS.SecretRef.Name
}
}
if pv.Spec.VsphereVolume != nil {
item.VolumeType = "vsphere_volume"
item.VsphereVolumeStoragePolicyID = pv.Spec.VsphereVolume.StoragePolicyID
item.VsphereVolumeStoragePolicyName = pv.Spec.VsphereVolume.StoragePolicyName
item.VsphereVolumeVolumePath = pv.Spec.VsphereVolume.VolumePath
item.FSType = &pv.Spec.VsphereVolume.FSType
}
results = append(results, k8s.ToMap(item))
}
if pvs.Continue == "" {
break
}
options.Continue = pvs.Continue
}
return results, nil
}

View File

@ -0,0 +1,63 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package core
import (
"context"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/Uptycs/kubequery/internal/k8s"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type persistentVolumeClaim struct {
k8s.CommonFields
v1.PersistentVolumeClaimSpec
Phase v1.PersistentVolumeClaimPhase
Capacity v1.ResourceList
Conditions []v1.PersistentVolumeClaimCondition
}
// PersistentVolumeClaimColumns returns kubernetes persistent volume claim fields as Osquery table columns.
func PersistentVolumeClaimColumns() []table.ColumnDefinition {
return k8s.GetSchema(&persistentVolumeClaim{})
}
// PersistentVolumeClaimsGenerate generates the kubernetes persistent volume claims as Osquery table data.
func PersistentVolumeClaimsGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
options := metav1.ListOptions{}
results := make([]map[string]string, 0)
for {
pvcs, err := k8s.GetClient().CoreV1().PersistentVolumeClaims(metav1.NamespaceAll).List(ctx, options)
if err != nil {
return nil, err
}
for _, pvc := range pvcs.Items {
item := &persistentVolumeClaim{
CommonFields: k8s.GetCommonFields(pvc.ObjectMeta),
PersistentVolumeClaimSpec: pvc.Spec,
Phase: pvc.Status.Phase,
Capacity: pvc.Status.Capacity,
Conditions: pvc.Status.Conditions,
}
results = append(results, k8s.ToMap(item))
}
if pvcs.Continue == "" {
break
}
options.Continue = pvcs.Continue
}
return results, nil
}

View File

@ -0,0 +1,233 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package core
import (
"context"
"strings"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/Uptycs/kubequery/internal/k8s"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type pod struct {
k8s.CommonNamespacedFields
k8s.CommonPodFields
v1.PodStatus
}
// PodColumns returns kubernetes pod fields as Osquery table columns.
func PodColumns() []table.ColumnDefinition {
return k8s.GetSchema(&pod{})
}
// PodsGenerate generates the kubernetes pods as Osquery table data.
func PodsGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
options := metav1.ListOptions{}
results := make([]map[string]string, 0)
for {
pods, err := k8s.GetClient().CoreV1().Pods(metav1.NamespaceAll).List(ctx, options)
if err != nil {
return nil, err
}
for _, p := range pods.Items {
item := &pod{
CommonNamespacedFields: k8s.GetCommonNamespacedFields(p.ObjectMeta),
CommonPodFields: k8s.GetCommonPodFields(p.Spec),
PodStatus: p.Status,
}
results = append(results, k8s.ToMap(item))
}
if pods.Continue == "" {
break
}
options.Continue = pods.Continue
}
return results, nil
}
type podContainer struct {
k8s.CommonNamespacedFields
k8s.CommonContainerFields
PodName string
ContainerType string
State v1.ContainerState
LastTerminationState v1.ContainerState
Ready bool
RestartCount int32
ImageRepo string
ImageID string
ContainerID string
Started *bool
}
// PodContainerColumns returns kubernetes pod container fields as Osquery table columns.
func PodContainerColumns() []table.ColumnDefinition {
return k8s.GetSchema(&podContainer{})
}
func getImageRepo(id string) string {
// docker.io/jaegertracing/jaeger-operator@sha256:5a3198179f7972028a29dd7fbf71ac7a21e0dbf46c85e8cc2c37e3b6a5ee26a4
index := strings.LastIndex(id, "@")
if index < 0 || index == len(id)-1 {
return ""
}
return id[0:index]
}
func cleanID(id string) string {
// containerd://4a8e3f149f24fb5d4429f4a38e86097e1aec3b6b174bb382a44c6706ad4406e1
// docker.io/jaegertracing/jaeger-operator@sha256:5a3198179f7972028a29dd7fbf71ac7a21e0dbf46c85e8cc2c37e3b6a5ee26a4
index := -1
for _, s := range []string{"/", ":", "@"} {
i := strings.LastIndex(id, s)
if i > -1 && i > index {
index = i
}
}
if index < 0 || index == len(id)-1 {
return id
}
return id[index+1:]
}
func updatePodContainerStatus(pc *podContainer, cs *v1.ContainerStatus) {
if cs != nil {
pc.State = cs.State
pc.LastTerminationState = cs.LastTerminationState
pc.Ready = cs.Ready
pc.RestartCount = cs.RestartCount
pc.ImageRepo = getImageRepo(cs.ImageID)
pc.ImageID = cleanID(cs.ImageID)
pc.ContainerID = cleanID(cs.ContainerID)
pc.Started = cs.Started
}
}
func createPodContainer(p v1.Pod, c v1.Container, cs *v1.ContainerStatus, containerType string) *podContainer {
item := &podContainer{
CommonNamespacedFields: k8s.GetParentCommonNamespacedFields(p.ObjectMeta, c.Name),
CommonContainerFields: k8s.GetCommonContainerFields(c),
PodName: p.Name,
ContainerType: containerType,
}
item.Name = c.Name
updatePodContainerStatus(item, cs)
return item
}
func createPodEphemeralContainer(p v1.Pod, c v1.EphemeralContainer, cs *v1.ContainerStatus) *podContainer {
item := &podContainer{
CommonNamespacedFields: k8s.GetParentCommonNamespacedFields(p.ObjectMeta, c.Name),
CommonContainerFields: k8s.GetCommonEphemeralContainerFields(c),
PodName: p.Name,
ContainerType: "ephemeral",
}
item.Name = c.Name
updatePodContainerStatus(item, cs)
return item
}
// PodContainersGenerate generates the kubernetes pod containers as Osquery table data.
func PodContainersGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
options := metav1.ListOptions{}
results := make([]map[string]string, 0)
for {
pods, err := k8s.GetClient().CoreV1().Pods(metav1.NamespaceAll).List(ctx, options)
if err != nil {
return nil, err
}
for _, p := range pods.Items {
for i, c := range p.Spec.InitContainers {
var cs *v1.ContainerStatus = nil
if len(p.Status.InitContainerStatuses) > i {
cs = &p.Status.InitContainerStatuses[i]
}
item := createPodContainer(p, c, cs, "init")
results = append(results, k8s.ToMap(item))
}
for i, c := range p.Spec.Containers {
var cs *v1.ContainerStatus = nil
if len(p.Status.ContainerStatuses) > i {
cs = &p.Status.ContainerStatuses[i]
}
item := createPodContainer(p, c, cs, "container")
results = append(results, k8s.ToMap(item))
}
for i, c := range p.Spec.EphemeralContainers {
var cs *v1.ContainerStatus = nil
if len(p.Status.EphemeralContainerStatuses) > i {
cs = &p.Status.EphemeralContainerStatuses[i]
}
item := createPodEphemeralContainer(p, c, cs)
results = append(results, k8s.ToMap(item))
}
}
if pods.Continue == "" {
break
}
options.Continue = pods.Continue
}
return results, nil
}
type podVolume struct {
k8s.CommonNamespacedFields
k8s.CommonVolumeFields
PodName string
}
// PodVolumeColumns returns kubernetes pod volume fields as Osquery table columns.
func PodVolumeColumns() []table.ColumnDefinition {
return k8s.GetSchema(&podVolume{})
}
// PodVolumesGenerate generates the kubernetes pod volumes as Osquery table data.
func PodVolumesGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
options := metav1.ListOptions{}
results := make([]map[string]string, 0)
for {
pods, err := k8s.GetClient().CoreV1().Pods(metav1.NamespaceAll).List(ctx, options)
if err != nil {
return nil, err
}
for _, p := range pods.Items {
for _, v := range p.Spec.Volumes {
item := &podVolume{
CommonNamespacedFields: k8s.GetCommonNamespacedFields(p.ObjectMeta),
CommonVolumeFields: k8s.GetCommonVolumeFields(v),
PodName: p.Name,
}
item.Name = v.Name
results = append(results, k8s.ToMap(item))
}
}
if pods.Continue == "" {
break
}
options.Continue = pods.Continue
}
return results, nil
}

View File

@ -0,0 +1,169 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package core
import (
"context"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/Uptycs/kubequery/internal/k8s"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type podTemplate struct {
k8s.CommonNamespacedFields
k8s.CommonPodFields
}
// PodTemplateColumns returns kubernetes pod template fields as Osquery table columns.
func PodTemplateColumns() []table.ColumnDefinition {
return k8s.GetSchema(&podTemplate{})
}
// PodTemplatesGenerate generates the kubernetes pod templates as Osquery table data.
func PodTemplatesGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
options := metav1.ListOptions{}
results := make([]map[string]string, 0)
for {
pts, err := k8s.GetClient().CoreV1().PodTemplates(metav1.NamespaceAll).List(ctx, options)
if err != nil {
return nil, err
}
for _, pt := range pts.Items {
item := &podTemplate{
CommonNamespacedFields: k8s.GetCommonNamespacedFields(pt.ObjectMeta),
CommonPodFields: k8s.GetCommonPodFields(pt.Template.Spec),
}
results = append(results, k8s.ToMap(item))
}
if pts.Continue == "" {
break
}
options.Continue = pts.Continue
}
return results, nil
}
type podTemplateContainer struct {
k8s.CommonNamespacedFields
k8s.CommonContainerFields
PodTemplateName string
ContainerType string
}
// PodTemplateContainerColumns returns kubernetes pod template container fields as Osquery table columns.
func PodTemplateContainerColumns() []table.ColumnDefinition {
return k8s.GetSchema(&podTemplateContainer{})
}
func createPodTemplateContainer(pt v1.PodTemplate, c v1.Container, containerType string) *podTemplateContainer {
item := &podTemplateContainer{
CommonNamespacedFields: k8s.GetParentCommonNamespacedFields(pt.ObjectMeta, c.Name),
CommonContainerFields: k8s.GetCommonContainerFields(c),
PodTemplateName: pt.Name,
ContainerType: containerType,
}
item.Name = c.Name
return item
}
func createPodTemplateEphemeralContainer(pt v1.PodTemplate, c v1.EphemeralContainer) *podTemplateContainer {
item := &podTemplateContainer{
CommonNamespacedFields: k8s.GetParentCommonNamespacedFields(pt.ObjectMeta, c.Name),
CommonContainerFields: k8s.GetCommonEphemeralContainerFields(c),
PodTemplateName: pt.Name,
ContainerType: "ephemeral",
}
item.Name = c.Name
return item
}
// PodTemplateContainersGenerate generates the kubernetes pod template containers as Osquery table data.
func PodTemplateContainersGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
options := metav1.ListOptions{}
results := make([]map[string]string, 0)
for {
pts, err := k8s.GetClient().CoreV1().PodTemplates(metav1.NamespaceAll).List(ctx, options)
if err != nil {
return nil, err
}
for _, pt := range pts.Items {
for _, c := range pt.Template.Spec.InitContainers {
item := createPodTemplateContainer(pt, c, "init")
results = append(results, k8s.ToMap(item))
}
for _, c := range pt.Template.Spec.Containers {
item := createPodTemplateContainer(pt, c, "container")
results = append(results, k8s.ToMap(item))
}
for _, c := range pt.Template.Spec.EphemeralContainers {
item := createPodTemplateEphemeralContainer(pt, c)
results = append(results, k8s.ToMap(item))
}
}
if pts.Continue == "" {
break
}
options.Continue = pts.Continue
}
return results, nil
}
type podTemplateVolume struct {
k8s.CommonNamespacedFields
k8s.CommonVolumeFields
PodTemplateName string
}
// PodTemplateVolumeColumns returns kubernetes pod template volume fields as Osquery table columns.
func PodTemplateVolumeColumns() []table.ColumnDefinition {
return k8s.GetSchema(&podTemplateVolume{})
}
// PodTemplateVolumesGenerate generates the kubernetes pod template volumes as Osquery table data.
func PodTemplateVolumesGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
options := metav1.ListOptions{}
results := make([]map[string]string, 0)
for {
pts, err := k8s.GetClient().CoreV1().PodTemplates(metav1.NamespaceAll).List(ctx, options)
if err != nil {
return nil, err
}
for _, pt := range pts.Items {
for _, v := range pt.Template.Spec.Volumes {
item := &podTemplateVolume{
CommonNamespacedFields: k8s.GetCommonNamespacedFields(pt.ObjectMeta),
CommonVolumeFields: k8s.GetCommonVolumeFields(v),
PodTemplateName: pt.Name,
}
item.Name = v.Name
results = append(results, k8s.ToMap(item))
}
}
if pts.Continue == "" {
break
}
options.Continue = pts.Continue
}
return results, nil
}

View File

@ -0,0 +1,118 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package core
import (
"context"
"testing"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/stretchr/testify/assert"
)
func TestPodsGenerate(t *testing.T) {
ps, err := PodsGenerate(context.TODO(), table.QueryContext{})
assert.Nil(t, err)
assert.Equal(t, []map[string]string{
{
"annotations": "{\"cni.projectcalico.org/podIP\":\"10.1.26.50/32\",\"cni.projectcalico.org/podIPs\":\"10.1.26.50/32\"}",
"cluster_uid": "d7fd8e77-93de-4742-9037-5db9a01e966a",
"conditions": "[{\"type\":\"Initialized\",\"status\":\"True\",\"lastProbeTime\":null,\"lastTransitionTime\":\"2021-01-21T01:08:25Z\"},{\"type\":\"Ready\",\"status\":\"True\",\"lastProbeTime\":null,\"lastTransitionTime\":\"2021-01-21T01:08:52Z\"},{\"type\":\"ContainersReady\",\"status\":\"True\",\"lastProbeTime\":null,\"lastTransitionTime\":\"2021-01-21T01:08:52Z\"},{\"type\":\"PodScheduled\",\"status\":\"True\",\"lastProbeTime\":null,\"lastTransitionTime\":\"2021-01-21T01:08:25Z\"}]",
"container_statuses": "[{\"name\":\"jaeger-operator\",\"state\":{\"running\":{\"startedAt\":\"2021-01-21T01:08:51Z\"}},\"lastState\":{\"terminated\":{\"exitCode\":1,\"reason\":\"Error\",\"startedAt\":\"2021-01-21T01:08:36Z\",\"finishedAt\":\"2021-01-21T01:08:36Z\",\"containerID\":\"containerd://d4c9607e13f2bd2eec99f5261693557963a1380cfe6aceda23b9e3d3d195962f\"}},\"ready\":true,\"restartCount\":2,\"image\":\"docker.io/jaegertracing/jaeger-operator:1.14.0\",\"imageID\":\"docker.io/jaegertracing/jaeger-operator@sha256:5a3198179f7972028a29dd7fbf71ac7a21e0dbf46c85e8cc2c37e3b6a5ee26a4\",\"containerID\":\"containerd://4a8e3f149f24fb5d4429f4a38e86097e1aec3b6b174bb382a44c6706ad4406e1\",\"started\":true}]",
"creation_timestamp": "1611191305",
"dns_policy": "ClusterFirst",
"enable_service_links": "1",
"host_ip": "192.168.0.28",
"host_ipc": "0",
"host_network": "0",
"host_pid": "0",
"labels": "{\"name\":\"jaeger-operator\",\"pod-template-hash\":\"5db4f9d996\"}",
"name": "jaeger-operator-5db4f9d996-pm7ld",
"namespace": "default",
"node_name": "seshu",
"phase": "Running",
"pod_ip": "10.1.26.50",
"pod_ips": "[{\"ip\":\"10.1.26.50\"}]",
"preemption_policy": "PreemptLowerPriority",
"priority": "0",
"qos_class": "BestEffort",
"restart_policy": "Always",
"scheduler_name": "default-scheduler",
"service_account_name": "jaeger-operator",
"start_time": "1611191305",
"termination_grace_period_seconds": "30",
"tolerations": "[{\"key\":\"node.kubernetes.io/not-ready\",\"operator\":\"Exists\",\"effect\":\"NoExecute\",\"tolerationSeconds\":300},{\"key\":\"node.kubernetes.io/unreachable\",\"operator\":\"Exists\",\"effect\":\"NoExecute\",\"tolerationSeconds\":300}]",
"uid": "2271363b-ffc9-4f00-984c-e0a125ee2d7a",
},
}, ps)
}
func TestPodContainersGenerate(t *testing.T) {
pcs, err := PodContainersGenerate(context.TODO(), table.QueryContext{})
assert.Nil(t, err)
assert.Equal(t, []map[string]string{
{
"annotations": "{\"cni.projectcalico.org/podIP\":\"10.1.26.50/32\",\"cni.projectcalico.org/podIPs\":\"10.1.26.50/32\"}",
"args": "[\"start\"]",
"cluster_uid": "d7fd8e77-93de-4742-9037-5db9a01e966a",
"container_id": "4a8e3f149f24fb5d4429f4a38e86097e1aec3b6b174bb382a44c6706ad4406e1",
"container_type": "container",
"creation_timestamp": "1611191305",
"env": "[{\"name\":\"WATCH_NAMESPACE\"},{\"name\":\"POD_NAME\",\"valueFrom\":{\"fieldRef\":{\"apiVersion\":\"v1\",\"fieldPath\":\"metadata.name\"}}},{\"name\":\"POD_NAMESPACE\",\"valueFrom\":{\"fieldRef\":{\"apiVersion\":\"v1\",\"fieldPath\":\"metadata.namespace\"}}},{\"name\":\"OPERATOR_NAME\",\"value\":\"jaeger-operator\"}]",
"image": "jaegertracing/jaeger-operator:1.14.0",
"image_repo": "docker.io/jaegertracing/jaeger-operator",
"image_id": "5a3198179f7972028a29dd7fbf71ac7a21e0dbf46c85e8cc2c37e3b6a5ee26a4",
"image_pull_policy": "Always",
"labels": "{\"name\":\"jaeger-operator\",\"pod-template-hash\":\"5db4f9d996\"}",
"last_termination_state": "{\"terminated\":{\"exitCode\":1,\"reason\":\"Error\",\"startedAt\":\"2021-01-21T01:08:36Z\",\"finishedAt\":\"2021-01-21T01:08:36Z\",\"containerID\":\"containerd://d4c9607e13f2bd2eec99f5261693557963a1380cfe6aceda23b9e3d3d195962f\"}}",
"name": "jaeger-operator",
"namespace": "default",
"pod_name": "jaeger-operator-5db4f9d996-pm7ld",
"ports": "[{\"name\":\"metrics\",\"containerPort\":8383,\"protocol\":\"TCP\"}]",
"ready": "1",
"restart_count": "2",
"started": "1",
"state": "{\"running\":{\"startedAt\":\"2021-01-21T01:08:51Z\"}}",
"stdin": "0",
"stdin_once": "0",
"termination_message_path": "/dev/termination-log",
"termination_message_policy": "File",
"tty": "0",
"uid": "2e7d1ce3-8546-5b73-beb8-46c109f37668",
"volume_mounts": "[{\"name\":\"jaeger-operator-token-c94jx\",\"readOnly\":true,\"mountPath\":\"/var/run/secrets/kubernetes.io/serviceaccount\"}]",
},
}, pcs)
}
func TestPodVolumesGenerate(t *testing.T) {
pcs, err := PodVolumesGenerate(context.TODO(), table.QueryContext{})
assert.Nil(t, err)
assert.Equal(t, []map[string]string{
{
"annotations": "{\"cni.projectcalico.org/podIP\":\"10.1.26.50/32\",\"cni.projectcalico.org/podIPs\":\"10.1.26.50/32\"}",
"aws_elastic_block_store_partition": "0",
"cluster_uid": "d7fd8e77-93de-4742-9037-5db9a01e966a",
"creation_timestamp": "1611191305",
"gce_persistent_disk_partition": "0",
"iscsi_discovery_chap_auth": "0",
"iscsi_lun": "0",
"iscsi_session_chap_auth": "0",
"labels": "{\"name\":\"jaeger-operator\",\"pod-template-hash\":\"5db4f9d996\"}",
"name": "jaeger-operator-token-c94jx",
"namespace": "default",
"pod_name": "jaeger-operator-5db4f9d996-pm7ld",
"scale_iossl_enabled": "0",
"secret_default_mode": "420",
"secret_name": "jaeger-operator-token-c94jx",
"uid": "2271363b-ffc9-4f00-984c-e0a125ee2d7a",
"volume_type": "secret",
},
}, pcs)
}

View File

@ -0,0 +1,61 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package core
import (
"context"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/Uptycs/kubequery/internal/k8s"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type resourceQuota struct {
k8s.CommonNamespacedFields
v1.ResourceQuotaSpec
StatusHard v1.ResourceList
StatusUsed v1.ResourceList
}
// ResourceQuotaColumns returns kubernetes resource quota fields as Osquery table columns.
func ResourceQuotaColumns() []table.ColumnDefinition {
return k8s.GetSchema(&resourceQuota{})
}
// ResourceQuotasGenerate generates the kubernetes resource quotas as Osquery table data.
func ResourceQuotasGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
options := metav1.ListOptions{}
results := make([]map[string]string, 0)
for {
quotas, err := k8s.GetClient().CoreV1().ResourceQuotas(metav1.NamespaceAll).List(ctx, options)
if err != nil {
return nil, err
}
for _, q := range quotas.Items {
item := &resourceQuota{
CommonNamespacedFields: k8s.GetCommonNamespacedFields(q.ObjectMeta),
ResourceQuotaSpec: q.Spec,
StatusHard: q.Status.Hard,
StatusUsed: q.Status.Used,
}
results = append(results, k8s.ToMap(item))
}
if quotas.Continue == "" {
break
}
options.Continue = quotas.Continue
}
return results, nil
}

View File

@ -0,0 +1,59 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package core
import (
"context"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/Uptycs/kubequery/internal/k8s"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type secret struct {
k8s.CommonNamespacedFields
Immutable *bool
Type v1.SecretType
}
// SecretColumns returns kubernetes secret fields as Osquery table columns.
func SecretColumns() []table.ColumnDefinition {
return k8s.GetSchema(&secret{})
}
// SecretsGenerate generates the kubernetes secrets as Osquery table data.
func SecretsGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
options := metav1.ListOptions{}
results := make([]map[string]string, 0)
for {
secrets, err := k8s.GetClient().CoreV1().Secrets(metav1.NamespaceAll).List(ctx, options)
if err != nil {
return nil, err
}
for _, s := range secrets.Items {
item := &secret{
CommonNamespacedFields: k8s.GetCommonNamespacedFields(s.ObjectMeta),
Immutable: s.Immutable,
Type: s.Type,
}
results = append(results, k8s.ToMap(item))
}
if secrets.Continue == "" {
break
}
options.Continue = secrets.Continue
}
return results, nil
}

View File

@ -0,0 +1,34 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package core
import (
"context"
"testing"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/stretchr/testify/assert"
)
func TestSecretsGenerate(t *testing.T) {
ss, err := SecretsGenerate(context.TODO(), table.QueryContext{})
assert.Nil(t, err)
assert.Equal(t, []map[string]string{
{
"annotations": "{\"istio.io/service-account.name\":\"jaeger-operator\"}",
"cluster_uid": "d7fd8e77-93de-4742-9037-5db9a01e966a",
"creation_timestamp": "1611191305",
"name": "istio.jaeger-operator",
"namespace": "default",
"type": "istio.io/key-and-cert",
"uid": "fb60f655-6b24-4f35-8e2d-17d7ca3ba7d4",
},
}, ss)
}

View File

@ -0,0 +1,59 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package core
import (
"context"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/Uptycs/kubequery/internal/k8s"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type service struct {
k8s.CommonNamespacedFields
v1.ServiceSpec
v1.ServiceStatus
}
// ServiceColumns returns kubernetes service fields as Osquery table columns.
func ServiceColumns() []table.ColumnDefinition {
return k8s.GetSchema(&service{})
}
// ServicesGenerate generates the kubernetes services as Osquery table data.
func ServicesGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
options := metav1.ListOptions{}
results := make([]map[string]string, 0)
for {
services, err := k8s.GetClient().CoreV1().Services(metav1.NamespaceAll).List(ctx, options)
if err != nil {
return nil, err
}
for _, s := range services.Items {
item := &service{
CommonNamespacedFields: k8s.GetCommonNamespacedFields(s.ObjectMeta),
ServiceSpec: s.Spec,
ServiceStatus: s.Status,
}
results = append(results, k8s.ToMap(item))
}
if services.Continue == "" {
break
}
options.Continue = services.Continue
}
return results, nil
}

View File

@ -0,0 +1,61 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package core
import (
"context"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/Uptycs/kubequery/internal/k8s"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type serviceAccount struct {
k8s.CommonNamespacedFields
Secrets []v1.ObjectReference
ImagePullSecrets []v1.LocalObjectReference
AutomountServiceAccountToken *bool
}
// ServiceAccountColumns returns kubernetes service account fields as Osquery table columns.
func ServiceAccountColumns() []table.ColumnDefinition {
return k8s.GetSchema(&serviceAccount{})
}
// ServiceAccountsGenerate generates the kubernetes service accounts as Osquery table data.
func ServiceAccountsGenerate(ctx context.Context, queryContext table.QueryContext) ([]map[string]string, error) {
options := metav1.ListOptions{}
results := make([]map[string]string, 0)
for {
sas, err := k8s.GetClient().CoreV1().ServiceAccounts(metav1.NamespaceAll).List(ctx, options)
if err != nil {
return nil, err
}
for _, sa := range sas.Items {
item := &serviceAccount{
CommonNamespacedFields: k8s.GetCommonNamespacedFields(sa.ObjectMeta),
Secrets: sa.Secrets,
ImagePullSecrets: sa.ImagePullSecrets,
AutomountServiceAccountToken: sa.AutomountServiceAccountToken,
}
results = append(results, k8s.ToMap(item))
}
if sas.Continue == "" {
break
}
options.Continue = sas.Continue
}
return results, nil
}

View File

@ -0,0 +1,35 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package core
import (
"context"
"testing"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/stretchr/testify/assert"
)
func TestServiceAccountsGenerate(t *testing.T) {
sas, err := ServiceAccountsGenerate(context.TODO(), table.QueryContext{})
assert.Nil(t, err)
assert.Equal(t, []map[string]string{
{
"annotations": "{\"kubectl.kubernetes.io/last-applied-configuration\":\"{\\\"apiVersion\\\":\\\"v1\\\",\\\"kind\\\":\\\"ServiceAccount\\\",\\\"metadata\\\":{\\\"annotations\\\":{},\\\"labels\\\":{\\\"app\\\":\\\"istio-ingressgateway\\\",\\\"chart\\\":\\\"gateways\\\",\\\"heritage\\\":\\\"Tiller\\\",\\\"release\\\":\\\"istio\\\"},\\\"name\\\":\\\"istio-ingressgateway-service-account\\\",\\\"namespace\\\":\\\"istio-system\\\"}}\\n\"}",
"cluster_uid": "d7fd8e77-93de-4742-9037-5db9a01e966a",
"creation_timestamp": "1611191143",
"labels": "{\"app\":\"istio-ingressgateway\",\"chart\":\"gateways\",\"heritage\":\"Tiller\",\"release\":\"istio\"}",
"name": "istio-ingressgateway-service-account",
"namespace": "istio-system",
"secrets": "[{\"name\":\"istio-ingressgateway-service-account-token-zmk8b\"}]",
"uid": "de09c78a-ea26-42ff-82d5-2f7d3f24a8d1",
},
}, sas)
}

View File

@ -0,0 +1,42 @@
/**
* Copyright (c) 2020-present, The kubequery authors
*
* This source code is licensed as defined by the LICENSE file found in the
* root directory of this source tree.
*
* SPDX-License-Identifier: (Apache-2.0 OR GPL-2.0-only)
*/
package core
import (
"context"
"testing"
"github.com/Uptycs/basequery-go/plugin/table"
"github.com/stretchr/testify/assert"
)
func TestServicesGenerate(t *testing.T) {
ss, err := ServicesGenerate(context.TODO(), table.QueryContext{})
assert.Nil(t, err)
assert.Equal(t, []map[string]string{
{
"cluster_ip": "10.152.183.187",
"cluster_ips": "[\"10.152.183.187\"]",
"cluster_uid": "d7fd8e77-93de-4742-9037-5db9a01e966a",
"creation_timestamp": "1611191332",
"health_check_node_port": "0",
"labels": "{\"name\":\"jaeger-operator\"}",
"load_balancer": "{}",
"name": "jaeger-operator",
"namespace": "default",
"ports": "[{\"name\":\"metrics\",\"protocol\":\"TCP\",\"port\":8383,\"targetPort\":8383}]",
"publish_not_ready_addresses": "0",
"selector": "{\"name\":\"jaeger-operator\"}",
"session_affinity": "None",
"type": "ClusterIP",
"uid": "d8dfda88-e2c5-479e-bb2d-d0964805a925",
},
}, ss)
}

View File

@ -0,0 +1,58 @@
{
"apiVersion": "v1",
"items": [
{
"apiVersion": "v1",
"conditions": [
{
"message": "ok",
"status": "True",
"type": "Healthy"
}
],
"kind": "ComponentStatus",
"metadata": {
"creationTimestamp": null,
"name": "scheduler",
"selfLink": "/api/v1/componentstatuses/scheduler"
}
},
{
"apiVersion": "v1",
"conditions": [
{
"message": "ok",
"status": "True",
"type": "Healthy"
}
],
"kind": "ComponentStatus",
"metadata": {
"creationTimestamp": null,
"name": "controller-manager",
"selfLink": "/api/v1/componentstatuses/controller-manager"
}
},
{
"apiVersion": "v1",
"conditions": [
{
"message": "{\"health\":\"true\"}",
"status": "True",
"type": "Healthy"
}
],
"kind": "ComponentStatus",
"metadata": {
"creationTimestamp": null,
"name": "etcd-0",
"selfLink": "/api/v1/componentstatuses/etcd-0"
}
}
],
"kind": "List",
"metadata": {
"resourceVersion": "",
"selfLink": ""
}
}

View File

@ -0,0 +1,43 @@
{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": {
"creationTimestamp": "2021-01-21T01:08:51Z",
"managedFields": [
{
"apiVersion": "v1",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:metadata": {
"f:ownerReferences": {
".": {},
"k:{\"uid\":\"2271363b-ffc9-4f00-984c-e0a125ee2d7a\"}": {
".": {},
"f:apiVersion": {},
"f:kind": {},
"f:name": {},
"f:uid": {}
}
}
}
},
"manager": "jaeger-operator",
"operation": "Update",
"time": "2021-01-21T01:08:51Z"
}
],
"name": "jaeger-operator-lock",
"namespace": "default",
"ownerReferences": [
{
"apiVersion": "v1",
"kind": "Pod",
"name": "jaeger-operator-5db4f9d996-pm7ld",
"uid": "2271363b-ffc9-4f00-984c-e0a125ee2d7a"
}
],
"resourceVersion": "451803",
"selfLink": "/api/v1/namespaces/default/configmaps/jaeger-operator-lock",
"uid": "eec6944c-5c13-4e30-8326-1a82e1962e4d"
}
}

View File

@ -0,0 +1,64 @@
{
"apiVersion": "v1",
"kind": "Endpoints",
"metadata": {
"annotations": {
"endpoints.kubernetes.io/last-change-trigger-time": "2021-01-20T20:08:52-05:00"
},
"creationTimestamp": "2021-01-21T01:08:52Z",
"labels": {
"name": "jaeger-operator"
},
"managedFields": [
{
"apiVersion": "v1",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:metadata": {
"f:annotations": {
".": {},
"f:endpoints.kubernetes.io/last-change-trigger-time": {}
},
"f:labels": {
".": {},
"f:name": {}
}
},
"f:subsets": {}
},
"manager": "kube-controller-manager",
"operation": "Update",
"time": "2021-01-21T01:08:52Z"
}
],
"name": "jaeger-operator",
"namespace": "default",
"resourceVersion": "451810",
"selfLink": "/api/v1/namespaces/default/endpoints/jaeger-operator",
"uid": "013741da-d7a5-4a2d-8f4b-792ac6a40dd3"
},
"subsets": [
{
"addresses": [
{
"ip": "10.1.26.50",
"nodeName": "seshu",
"targetRef": {
"kind": "Pod",
"name": "jaeger-operator-5db4f9d996-pm7ld",
"namespace": "default",
"resourceVersion": "451808",
"uid": "2271363b-ffc9-4f00-984c-e0a125ee2d7a"
}
}
],
"ports": [
{
"name": "metrics",
"port": 8383,
"protocol": "TCP"
}
]
}
]
}

View File

@ -0,0 +1,275 @@
{
"apiVersion": "v1",
"items": [
{
"apiVersion": "v1",
"kind": "Namespace",
"metadata": {
"creationTimestamp": "2021-01-12T18:30:15Z",
"managedFields": [
{
"apiVersion": "v1",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:status": {
"f:phase": {}
}
},
"manager": "kube-apiserver",
"operation": "Update",
"time": "2021-01-12T18:30:15Z"
}
],
"name": "kube-system",
"resourceVersion": "11",
"selfLink": "/api/v1/namespaces/kube-system",
"uid": "ebca5546-b939-4765-bf3d-869ac644ea0f"
},
"spec": {
"finalizers": [
"kubernetes"
]
},
"status": {
"phase": "Active"
}
},
{
"apiVersion": "v1",
"kind": "Namespace",
"metadata": {
"creationTimestamp": "2021-01-12T18:30:15Z",
"managedFields": [
{
"apiVersion": "v1",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:status": {
"f:phase": {}
}
},
"manager": "kube-apiserver",
"operation": "Update",
"time": "2021-01-12T18:30:15Z"
}
],
"name": "kube-public",
"resourceVersion": "32",
"selfLink": "/api/v1/namespaces/kube-public",
"uid": "6c719dfa-3de8-477b-a650-8bf9e2f12ee0"
},
"spec": {
"finalizers": [
"kubernetes"
]
},
"status": {
"phase": "Active"
}
},
{
"apiVersion": "v1",
"kind": "Namespace",
"metadata": {
"creationTimestamp": "2021-01-12T18:30:15Z",
"managedFields": [
{
"apiVersion": "v1",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:status": {
"f:phase": {}
}
},
"manager": "kube-apiserver",
"operation": "Update",
"time": "2021-01-12T18:30:15Z"
}
],
"name": "kube-node-lease",
"resourceVersion": "44",
"selfLink": "/api/v1/namespaces/kube-node-lease",
"uid": "a8f303fd-0074-475f-935a-122cf8b6d1ad"
},
"spec": {
"finalizers": [
"kubernetes"
]
},
"status": {
"phase": "Active"
}
},
{
"apiVersion": "v1",
"kind": "Namespace",
"metadata": {
"creationTimestamp": "2021-01-12T18:30:16Z",
"managedFields": [
{
"apiVersion": "v1",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:status": {
"f:phase": {}
}
},
"manager": "kube-apiserver",
"operation": "Update",
"time": "2021-01-12T18:30:16Z"
}
],
"name": "default",
"resourceVersion": "149",
"selfLink": "/api/v1/namespaces/default",
"uid": "7b50dc9c-6149-4cac-a0d0-52bf0fa5356d"
},
"spec": {
"finalizers": [
"kubernetes"
]
},
"status": {
"phase": "Active"
}
},
{
"apiVersion": "v1",
"kind": "Namespace",
"metadata": {
"annotations": {
"kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"Namespace\",\"metadata\":{\"annotations\":{},\"name\":\"ingress\"}}\n"
},
"creationTimestamp": "2021-01-21T01:04:07Z",
"managedFields": [
{
"apiVersion": "v1",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:metadata": {
"f:annotations": {
".": {},
"f:kubectl.kubernetes.io/last-applied-configuration": {}
}
},
"f:status": {
"f:phase": {}
}
},
"manager": "kubectl-client-side-apply",
"operation": "Update",
"time": "2021-01-21T01:04:07Z"
}
],
"name": "ingress",
"resourceVersion": "450124",
"selfLink": "/api/v1/namespaces/ingress",
"uid": "7653c4b9-3df2-493e-ae28-5e3a777f7e76"
},
"spec": {
"finalizers": [
"kubernetes"
]
},
"status": {
"phase": "Active"
}
},
{
"apiVersion": "v1",
"kind": "Namespace",
"metadata": {
"annotations": {
"kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"Namespace\",\"metadata\":{\"annotations\":{},\"labels\":{\"istio-injection\":\"disabled\"},\"name\":\"istio-system\"}}\n"
},
"creationTimestamp": "2021-01-21T01:05:43Z",
"labels": {
"istio-injection": "disabled"
},
"managedFields": [
{
"apiVersion": "v1",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:metadata": {
"f:annotations": {
".": {},
"f:kubectl.kubernetes.io/last-applied-configuration": {}
},
"f:labels": {
".": {},
"f:istio-injection": {}
}
},
"f:status": {
"f:phase": {}
}
},
"manager": "kubectl-client-side-apply",
"operation": "Update",
"time": "2021-01-21T01:05:43Z"
}
],
"name": "istio-system",
"resourceVersion": "450427",
"selfLink": "/api/v1/namespaces/istio-system",
"uid": "7f931f07-f8d0-4198-bf16-e459914e1866"
},
"spec": {
"finalizers": [
"kubernetes"
]
},
"status": {
"phase": "Active"
}
},
{
"apiVersion": "v1",
"kind": "Namespace",
"metadata": {
"annotations": {
"kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"Namespace\",\"metadata\":{\"annotations\":{},\"name\":\"monitoring\"}}\n"
},
"creationTimestamp": "2021-01-21T01:10:49Z",
"managedFields": [
{
"apiVersion": "v1",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:metadata": {
"f:annotations": {
".": {},
"f:kubectl.kubernetes.io/last-applied-configuration": {}
}
},
"f:status": {
"f:phase": {}
}
},
"manager": "kubectl-client-side-apply",
"operation": "Update",
"time": "2021-01-21T01:10:49Z"
}
],
"name": "monitoring",
"resourceVersion": "452095",
"selfLink": "/api/v1/namespaces/monitoring",
"uid": "afb98a87-39bb-4c8f-b0dd-8ea3683ba745"
},
"spec": {
"finalizers": [
"kubernetes"
]
},
"status": {
"phase": "Active"
}
}
],
"kind": "List",
"metadata": {
"resourceVersion": "",
"selfLink": ""
}
}

View File

@ -0,0 +1,527 @@
{
"apiVersion": "v1",
"kind": "Node",
"metadata": {
"annotations": {
"node.alpha.kubernetes.io/ttl": "0",
"projectcalico.org/IPv4Address": "192.168.192.1/20",
"projectcalico.org/IPv4VXLANTunnelAddr": "10.1.26.0",
"volumes.kubernetes.io/controller-managed-attach-detach": "true"
},
"creationTimestamp": "2021-01-12T18:30:24Z",
"labels": {
"beta.kubernetes.io/arch": "amd64",
"beta.kubernetes.io/os": "linux",
"kubernetes.io/arch": "amd64",
"kubernetes.io/hostname": "seshu",
"kubernetes.io/os": "linux",
"microk8s.io/cluster": "true"
},
"managedFields": [
{
"apiVersion": "v1",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:metadata": {
"f:annotations": {
"f:projectcalico.org/IPv4Address": {},
"f:projectcalico.org/IPv4VXLANTunnelAddr": {}
}
},
"f:status": {
"f:conditions": {
"k:{\"type\":\"NetworkUnavailable\"}": {
".": {},
"f:lastHeartbeatTime": {},
"f:lastTransitionTime": {},
"f:message": {},
"f:reason": {},
"f:status": {},
"f:type": {}
}
}
}
},
"manager": "calico-node",
"operation": "Update",
"time": "2021-01-12T18:30:48Z"
},
{
"apiVersion": "v1",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:metadata": {
"f:annotations": {
".": {},
"f:volumes.kubernetes.io/controller-managed-attach-detach": {}
},
"f:labels": {
".": {},
"f:beta.kubernetes.io/arch": {},
"f:beta.kubernetes.io/os": {},
"f:kubernetes.io/arch": {},
"f:kubernetes.io/hostname": {},
"f:kubernetes.io/os": {},
"f:microk8s.io/cluster": {}
}
},
"f:status": {
"f:addresses": {
".": {},
"k:{\"type\":\"Hostname\"}": {
".": {},
"f:address": {},
"f:type": {}
},
"k:{\"type\":\"InternalIP\"}": {
".": {},
"f:address": {},
"f:type": {}
}
},
"f:allocatable": {
".": {},
"f:cpu": {},
"f:ephemeral-storage": {},
"f:hugepages-1Gi": {},
"f:hugepages-2Mi": {},
"f:memory": {},
"f:pods": {}
},
"f:capacity": {
".": {},
"f:cpu": {},
"f:ephemeral-storage": {},
"f:hugepages-1Gi": {},
"f:hugepages-2Mi": {},
"f:memory": {},
"f:pods": {}
},
"f:conditions": {
".": {},
"k:{\"type\":\"DiskPressure\"}": {
".": {},
"f:lastHeartbeatTime": {},
"f:lastTransitionTime": {},
"f:message": {},
"f:reason": {},
"f:status": {},
"f:type": {}
},
"k:{\"type\":\"MemoryPressure\"}": {
".": {},
"f:lastHeartbeatTime": {},
"f:lastTransitionTime": {},
"f:message": {},
"f:reason": {},
"f:status": {},
"f:type": {}
},
"k:{\"type\":\"PIDPressure\"}": {
".": {},
"f:lastHeartbeatTime": {},
"f:lastTransitionTime": {},
"f:message": {},
"f:reason": {},
"f:status": {},
"f:type": {}
},
"k:{\"type\":\"Ready\"}": {
".": {},
"f:lastHeartbeatTime": {},
"f:lastTransitionTime": {},
"f:message": {},
"f:reason": {},
"f:status": {},
"f:type": {}
}
},
"f:daemonEndpoints": {
"f:kubeletEndpoint": {
"f:Port": {}
}
},
"f:images": {},
"f:nodeInfo": {
"f:architecture": {},
"f:bootID": {},
"f:containerRuntimeVersion": {},
"f:kernelVersion": {},
"f:kubeProxyVersion": {},
"f:kubeletVersion": {},
"f:machineID": {},
"f:operatingSystem": {},
"f:osImage": {},
"f:systemUUID": {}
}
}
},
"manager": "kubelet",
"operation": "Update",
"time": "2021-01-12T18:31:34Z"
},
{
"apiVersion": "v1",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:metadata": {
"f:annotations": {
"f:node.alpha.kubernetes.io/ttl": {}
}
}
},
"manager": "kube-controller-manager",
"operation": "Update",
"time": "2021-01-21T01:10:50Z"
}
],
"name": "seshu",
"resourceVersion": "499998",
"selfLink": "/api/v1/nodes/seshu",
"uid": "d0d45111-421d-4d4f-89c9-3e75ca2dc06c"
},
"spec": {},
"status": {
"addresses": [
{
"address": "192.168.0.28",
"type": "InternalIP"
},
{
"address": "seshu",
"type": "Hostname"
}
],
"allocatable": {
"cpu": "12",
"ephemeral-storage": "958151776Ki",
"hugepages-1Gi": "0",
"hugepages-2Mi": "0",
"memory": "32411744Ki",
"pods": "110"
},
"capacity": {
"cpu": "12",
"ephemeral-storage": "959200352Ki",
"hugepages-1Gi": "0",
"hugepages-2Mi": "0",
"memory": "32514144Ki",
"pods": "110"
},
"conditions": [
{
"lastHeartbeatTime": "2021-01-20T16:31:53Z",
"lastTransitionTime": "2021-01-20T16:31:53Z",
"message": "Calico is running on this node",
"reason": "CalicoIsUp",
"status": "False",
"type": "NetworkUnavailable"
},
{
"lastHeartbeatTime": "2021-01-21T19:24:08Z",
"lastTransitionTime": "2021-01-12T18:30:24Z",
"message": "kubelet has sufficient memory available",
"reason": "KubeletHasSufficientMemory",
"status": "False",
"type": "MemoryPressure"
},
{
"lastHeartbeatTime": "2021-01-21T19:24:08Z",
"lastTransitionTime": "2021-01-12T18:30:24Z",
"message": "kubelet has no disk pressure",
"reason": "KubeletHasNoDiskPressure",
"status": "False",
"type": "DiskPressure"
},
{
"lastHeartbeatTime": "2021-01-21T19:24:08Z",
"lastTransitionTime": "2021-01-12T18:30:24Z",
"message": "kubelet has sufficient PID available",
"reason": "KubeletHasSufficientPID",
"status": "False",
"type": "PIDPressure"
},
{
"lastHeartbeatTime": "2021-01-21T19:24:08Z",
"lastTransitionTime": "2021-01-21T01:12:31Z",
"message": "kubelet is posting ready status. AppArmor enabled",
"reason": "KubeletReady",
"status": "True",
"type": "Ready"
}
],
"daemonEndpoints": {
"kubeletEndpoint": {
"Port": 10250
}
},
"images": [
{
"names": [
"docker.io/library/kubequery:latest"
],
"sizeBytes": 202523444
},
{
"names": null,
"sizeBytes": 174592418
},
{
"names": [
"k8s.gcr.io/ingress-nginx/controller@sha256:fc4979d8b8443a831c9789b5155cded454cb7de737a8b727bc2ba0106d2eae8b",
"k8s.gcr.io/ingress-nginx/controller:v0.35.0"
],
"sizeBytes": 111763794
},
{
"names": [
"docker.io/istio/proxyv2@sha256:3ad9ee2b43b299e5e6d97aaea5ed47dbf3da9293733607d9b52f358313e852ae",
"docker.io/istio/proxyv2:1.5.1"
],
"sizeBytes": 106728139
},
{
"names": [
"docker.io/jaegertracing/jaeger-operator@sha256:5a3198179f7972028a29dd7fbf71ac7a21e0dbf46c85e8cc2c37e3b6a5ee26a4",
"docker.io/jaegertracing/jaeger-operator:1.14.0"
],
"sizeBytes": 99946252
},
{
"names": [
"docker.io/calico/node@sha256:cb9dea7b86471c71925ae318f7c60af72d9ddf1dab0fe2029832a671b83bba6a",
"docker.io/calico/node:v3.13.2"
],
"sizeBytes": 88917441
},
{
"names": [
"docker.io/istio/mixer@sha256:92940f04e9aa20a41e330eb8a00a0b8ee7a3f4029dcdadfca4a5d009774474b2",
"docker.io/istio/mixer:1.5.1"
],
"sizeBytes": 86988340
},
{
"names": [
"docker.io/istio/pilot@sha256:818aecc1c73c53af9091ac1d4f500d9d7cec6d135d372d03cffab1addaff4ec0",
"docker.io/istio/pilot:1.5.1"
],
"sizeBytes": 85950908
},
{
"names": [
"docker.io/uptycs/kubequery@sha256:96b6c15753941f58e97fc6f80ee7ec06ce63d48a14b53ee0cc1dd10dc3585e7d",
"docker.io/uptycs/kubequery:latest"
],
"sizeBytes": 82661645
},
{
"names": [
"docker.io/istio/galley@sha256:d69acf890e5c82cb0c000fc15c540777ee566ae225762d85f157f69c9665338c",
"docker.io/istio/galley:1.5.1"
],
"sizeBytes": 82020368
},
{
"names": [
"docker.io/istio/sidecar_injector@sha256:cf334211f192378e7fcb66baeeb43412e483e34d739e93711d0a61568dd00462",
"docker.io/istio/sidecar_injector:1.5.1"
],
"sizeBytes": 77988679
},
{
"names": [
"docker.io/calico/cni@sha256:bbf7e3ac3f80d0a356a6c27b095bd313d1106f8ed84f85850816ed79295843c1",
"docker.io/calico/cni:v3.13.2"
],
"sizeBytes": 76710099
},
{
"names": [
"docker.io/istio/kubectl@sha256:83ea57063cf3344a2462c5bbaa5b125810f2e8ef7283d2ba3bfd9393e624b80f",
"docker.io/istio/kubectl:1.5.1"
],
"sizeBytes": 76608582
},
{
"names": [
"docker.io/grafana/grafana@sha256:bd55ea2bad17f5016431734b42fdfc202ebdc7d08b6c4ad35ebb03d06efdff69",
"docker.io/grafana/grafana:6.4.3"
],
"sizeBytes": 76169588
},
{
"names": [
"quay.io/kiali/kiali:v1.9"
],
"sizeBytes": 75529164
},
{
"names": [
"docker.io/istio/citadel@sha256:92b985411af9844b75c5fc9c39c33fc27ef549c31b5221358f334062aadb86ec",
"docker.io/istio/citadel:1.5.1"
],
"sizeBytes": 72604439
},
{
"names": [
"docker.io/kubernetesui/dashboard@sha256:06868692fb9a7f2ede1a06de1b7b32afabc40ec739c1181d83b5ed3eb147ec6e",
"docker.io/kubernetesui/dashboard:v2.0.0"
],
"sizeBytes": 66209190
},
{
"names": [
"docker.io/grafana/grafana@sha256:89304bc2335f4976618548d7b93d165ed67369d3a051d2f627fc4e0aa3d0aff1",
"docker.io/grafana/grafana:7.1.0"
],
"sizeBytes": 59911815
},
{
"names": [
"quay.io/prometheus/prometheus@sha256:d4ba4dd1a9ebb90916d0bfed3c204adcb118ed24546bf8dd2e6b30fc0fd2009e",
"quay.io/prometheus/prometheus:v2.20.0"
],
"sizeBytes": 59435495
},
{
"names": [
"docker.io/prom/prometheus@sha256:cd93b8711bb92eb9c437d74217311519e0a93bc55779aa664325dc83cd13cb32",
"docker.io/prom/prometheus:v2.12.0"
],
"sizeBytes": 54819393
},
{
"names": [
"docker.io/calico/pod2daemon-flexvol@sha256:0022da5a9a89512f8a117f12d2088b3f1f8f22c094ee15aae24d58085f2c186a",
"docker.io/calico/pod2daemon-flexvol:v3.13.2"
],
"sizeBytes": 37530211
},
{
"names": [
"quay.io/prometheus/alertmanager@sha256:24a5204b418e8fa0214cfb628486749003b039c279c56b5bddb5b10cd100d926",
"quay.io/prometheus/alertmanager:v0.21.0"
],
"sizeBytes": 27097956
},
{
"names": [
"docker.io/jaegertracing/all-in-one@sha256:738442983b772a5d413c8a2c44a5563956adaff224e5b38f52a959124dafc119",
"docker.io/jaegertracing/all-in-one:1.16"
],
"sizeBytes": 23571671
},
{
"names": [
"docker.io/directxman12/k8s-prometheus-adapter@sha256:44558d3ae98467e44fee72ebc3948ce59630996013a51d49cf925682a7b87c18",
"docker.io/directxman12/k8s-prometheus-adapter:v0.7.0"
],
"sizeBytes": 23407634
},
{
"names": [
"docker.io/jaegertracing/all-in-one@sha256:021aefafecbb5559078206996f1f4e8fc5907debab047f4fcc5c837689a66cfa",
"docker.io/jaegertracing/all-in-one:1.14.0"
],
"sizeBytes": 23208939
},
{
"names": [
"docker.io/calico/kube-controllers@sha256:a635173cbe9deb33deba9baadffd933f61c63fbdadc0e3fa60ff1a14198c1da8",
"docker.io/calico/kube-controllers:v3.13.2"
],
"sizeBytes": 23132265
},
{
"names": [
"quay.io/brancz/kube-rbac-proxy@sha256:05e15e1164fd7ac85f5702b3f87ef548f4e00de3a79e6c4a6a34c92035497a9a",
"quay.io/brancz/kube-rbac-proxy:v0.8.0"
],
"sizeBytes": 19991394
},
{
"names": [
"docker.io/kubernetesui/metrics-scraper@sha256:555981a24f184420f3be0c79d4efb6c948a85cfce84034f85a563f4151a81cbf",
"docker.io/kubernetesui/metrics-scraper:v1.0.4"
],
"sizeBytes": 16020077
},
{
"names": [
"docker.io/coredns/coredns@sha256:41bee6992c2ed0f4628fcef75751048927bcd6b1cee89c79f6acb63ca5474d5a",
"docker.io/coredns/coredns:1.6.6"
],
"sizeBytes": 12932169
},
{
"names": [
"quay.io/coreos/prometheus-operator@sha256:a54e806fb27d2fb0251da4f3b2a3bb5320759af63a54a755788304775f2384a7",
"quay.io/coreos/prometheus-operator:v0.40.0"
],
"sizeBytes": 12496211
},
{
"names": [
"quay.io/prometheus/node-exporter@sha256:a2f29256e53cc3e0b64d7a472512600b2e9410347d53cdc85b49f659c17e02ee",
"quay.io/prometheus/node-exporter:v0.18.1"
],
"sizeBytes": 11122661
},
{
"names": [
"gcr.io/k8s-staging-kube-state-metrics/kube-state-metrics@sha256:9718f2e7999e75f4993e312fccada801c0eb98eaba73db072f0f806d67fcc238",
"gcr.io/k8s-staging-kube-state-metrics/kube-state-metrics:v1.9.7"
],
"sizeBytes": 10782953
},
{
"names": [
"k8s.gcr.io/metrics-server-amd64@sha256:c9c4e95068b51d6b33a9dccc61875df07dc650abbf4ac1a19d58b4628f89288b",
"k8s.gcr.io/metrics-server-amd64:v0.3.6"
],
"sizeBytes": 10542830
},
{
"names": [
"docker.io/cdkbot/hostpath-provisioner-amd64@sha256:339f78eabc68ffb1656d584e41f121cb4d2b667565428c8dde836caf5b8a0228",
"docker.io/cdkbot/hostpath-provisioner-amd64:1.0.0"
],
"sizeBytes": 9745308
},
{
"names": [
"quay.io/coreos/prometheus-config-reloader@sha256:c679a143b24b7731ad1577a9865aa3805426cbf1b25e30807b951dff68466ffd",
"quay.io/coreos/prometheus-config-reloader:v0.40.0"
],
"sizeBytes": 4254190
},
{
"names": [
"docker.io/jimmidyson/configmap-reload@sha256:d107c7a235c266273b1c3502a391fec374430e5625539403d0de797fa9c556a2",
"docker.io/jimmidyson/configmap-reload:v0.3.0"
],
"sizeBytes": 4063371
},
{
"names": [
"k8s.gcr.io/pause@sha256:f78411e19d84a252e53bff71a4407a5686c46983a2c2eeed83929b888179acea",
"k8s.gcr.io/pause:3.1"
],
"sizeBytes": 317164
}
],
"nodeInfo": {
"architecture": "amd64",
"bootID": "0b51cb6f-120b-4557-b74a-e53a5f4f00d5",
"containerRuntimeVersion": "containerd://1.3.7",
"kernelVersion": "5.4.0-60-generic",
"kubeProxyVersion": "v1.20.1-34+e7db93d188d0d1",
"kubeletVersion": "v1.20.1-34+e7db93d188d0d1",
"machineID": "c73ef4a4ef2a4ec19a75719b63db3bb7",
"operatingSystem": "linux",
"osImage": "Ubuntu 20.04.1 LTS",
"systemUUID": "4c4c4544-0044-3510-8058-c6c04f5a5932"
}
}
}

View File

@ -0,0 +1,344 @@
{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"annotations": {
"cni.projectcalico.org/podIP": "10.1.26.50/32",
"cni.projectcalico.org/podIPs": "10.1.26.50/32"
},
"creationTimestamp": "2021-01-21T01:08:25Z",
"generateName": "jaeger-operator-5db4f9d996-",
"labels": {
"name": "jaeger-operator",
"pod-template-hash": "5db4f9d996"
},
"managedFields": [
{
"apiVersion": "v1",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:metadata": {
"f:generateName": {},
"f:labels": {
".": {},
"f:name": {},
"f:pod-template-hash": {}
},
"f:ownerReferences": {
".": {},
"k:{\"uid\":\"2efeb411-ff99-434b-a5a2-4e06c2b0afaa\"}": {
".": {},
"f:apiVersion": {},
"f:blockOwnerDeletion": {},
"f:controller": {},
"f:kind": {},
"f:name": {},
"f:uid": {}
}
}
},
"f:spec": {
"f:containers": {
"k:{\"name\":\"jaeger-operator\"}": {
".": {},
"f:args": {},
"f:env": {
".": {},
"k:{\"name\":\"OPERATOR_NAME\"}": {
".": {},
"f:name": {},
"f:value": {}
},
"k:{\"name\":\"POD_NAME\"}": {
".": {},
"f:name": {},
"f:valueFrom": {
".": {},
"f:fieldRef": {
".": {},
"f:apiVersion": {},
"f:fieldPath": {}
}
}
},
"k:{\"name\":\"POD_NAMESPACE\"}": {
".": {},
"f:name": {},
"f:valueFrom": {
".": {},
"f:fieldRef": {
".": {},
"f:apiVersion": {},
"f:fieldPath": {}
}
}
},
"k:{\"name\":\"WATCH_NAMESPACE\"}": {
".": {},
"f:name": {}
}
},
"f:image": {},
"f:imagePullPolicy": {},
"f:name": {},
"f:ports": {
".": {},
"k:{\"containerPort\":8383,\"protocol\":\"TCP\"}": {
".": {},
"f:containerPort": {},
"f:name": {},
"f:protocol": {}
}
},
"f:resources": {},
"f:terminationMessagePath": {},
"f:terminationMessagePolicy": {}
}
},
"f:dnsPolicy": {},
"f:enableServiceLinks": {},
"f:restartPolicy": {},
"f:schedulerName": {},
"f:securityContext": {},
"f:serviceAccount": {},
"f:serviceAccountName": {},
"f:terminationGracePeriodSeconds": {}
}
},
"manager": "kube-controller-manager",
"operation": "Update",
"time": "2021-01-21T01:08:25Z"
},
{
"apiVersion": "v1",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:metadata": {
"f:annotations": {
".": {},
"f:cni.projectcalico.org/podIP": {},
"f:cni.projectcalico.org/podIPs": {}
}
}
},
"manager": "calico",
"operation": "Update",
"time": "2021-01-21T01:08:26Z"
},
{
"apiVersion": "v1",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:status": {
"f:conditions": {
"k:{\"type\":\"ContainersReady\"}": {
".": {},
"f:lastProbeTime": {},
"f:lastTransitionTime": {},
"f:status": {},
"f:type": {}
},
"k:{\"type\":\"Initialized\"}": {
".": {},
"f:lastProbeTime": {},
"f:lastTransitionTime": {},
"f:status": {},
"f:type": {}
},
"k:{\"type\":\"Ready\"}": {
".": {},
"f:lastProbeTime": {},
"f:lastTransitionTime": {},
"f:status": {},
"f:type": {}
}
},
"f:containerStatuses": {},
"f:hostIP": {},
"f:phase": {},
"f:podIP": {},
"f:podIPs": {
".": {},
"k:{\"ip\":\"10.1.26.50\"}": {
".": {},
"f:ip": {}
}
},
"f:startTime": {}
}
},
"manager": "kubelet",
"operation": "Update",
"time": "2021-01-21T01:08:52Z"
}
],
"name": "jaeger-operator-5db4f9d996-pm7ld",
"namespace": "default",
"ownerReferences": [
{
"apiVersion": "apps/v1",
"blockOwnerDeletion": true,
"controller": true,
"kind": "ReplicaSet",
"name": "jaeger-operator-5db4f9d996",
"uid": "2efeb411-ff99-434b-a5a2-4e06c2b0afaa"
}
],
"resourceVersion": "451808",
"selfLink": "/api/v1/namespaces/default/pods/jaeger-operator-5db4f9d996-pm7ld",
"uid": "2271363b-ffc9-4f00-984c-e0a125ee2d7a"
},
"spec": {
"containers": [
{
"args": [
"start"
],
"env": [
{
"name": "WATCH_NAMESPACE"
},
{
"name": "POD_NAME",
"valueFrom": {
"fieldRef": {
"apiVersion": "v1",
"fieldPath": "metadata.name"
}
}
},
{
"name": "POD_NAMESPACE",
"valueFrom": {
"fieldRef": {
"apiVersion": "v1",
"fieldPath": "metadata.namespace"
}
}
},
{
"name": "OPERATOR_NAME",
"value": "jaeger-operator"
}
],
"image": "jaegertracing/jaeger-operator:1.14.0",
"imagePullPolicy": "Always",
"name": "jaeger-operator",
"ports": [
{
"containerPort": 8383,
"name": "metrics",
"protocol": "TCP"
}
],
"resources": {},
"terminationMessagePath": "/dev/termination-log",
"terminationMessagePolicy": "File",
"volumeMounts": [
{
"mountPath": "/var/run/secrets/kubernetes.io/serviceaccount",
"name": "jaeger-operator-token-c94jx",
"readOnly": true
}
]
}
],
"dnsPolicy": "ClusterFirst",
"enableServiceLinks": true,
"nodeName": "seshu",
"preemptionPolicy": "PreemptLowerPriority",
"priority": 0,
"restartPolicy": "Always",
"schedulerName": "default-scheduler",
"securityContext": {},
"serviceAccount": "jaeger-operator",
"serviceAccountName": "jaeger-operator",
"terminationGracePeriodSeconds": 30,
"tolerations": [
{
"effect": "NoExecute",
"key": "node.kubernetes.io/not-ready",
"operator": "Exists",
"tolerationSeconds": 300
},
{
"effect": "NoExecute",
"key": "node.kubernetes.io/unreachable",
"operator": "Exists",
"tolerationSeconds": 300
}
],
"volumes": [
{
"name": "jaeger-operator-token-c94jx",
"secret": {
"defaultMode": 420,
"secretName": "jaeger-operator-token-c94jx"
}
}
]
},
"status": {
"conditions": [
{
"lastProbeTime": null,
"lastTransitionTime": "2021-01-21T01:08:25Z",
"status": "True",
"type": "Initialized"
},
{
"lastProbeTime": null,
"lastTransitionTime": "2021-01-21T01:08:52Z",
"status": "True",
"type": "Ready"
},
{
"lastProbeTime": null,
"lastTransitionTime": "2021-01-21T01:08:52Z",
"status": "True",
"type": "ContainersReady"
},
{
"lastProbeTime": null,
"lastTransitionTime": "2021-01-21T01:08:25Z",
"status": "True",
"type": "PodScheduled"
}
],
"containerStatuses": [
{
"containerID": "containerd://4a8e3f149f24fb5d4429f4a38e86097e1aec3b6b174bb382a44c6706ad4406e1",
"image": "docker.io/jaegertracing/jaeger-operator:1.14.0",
"imageID": "docker.io/jaegertracing/jaeger-operator@sha256:5a3198179f7972028a29dd7fbf71ac7a21e0dbf46c85e8cc2c37e3b6a5ee26a4",
"lastState": {
"terminated": {
"containerID": "containerd://d4c9607e13f2bd2eec99f5261693557963a1380cfe6aceda23b9e3d3d195962f",
"exitCode": 1,
"finishedAt": "2021-01-21T01:08:36Z",
"reason": "Error",
"startedAt": "2021-01-21T01:08:36Z"
}
},
"name": "jaeger-operator",
"ready": true,
"restartCount": 2,
"started": true,
"state": {
"running": {
"startedAt": "2021-01-21T01:08:51Z"
}
}
}
],
"hostIP": "192.168.0.28",
"phase": "Running",
"podIP": "10.1.26.50",
"podIPs": [
{
"ip": "10.1.26.50"
}
],
"qosClass": "BestEffort",
"startTime": "2021-01-21T01:08:25Z"
}
}

View File

@ -0,0 +1,44 @@
{
"apiVersion": "v1",
"data": {
"cert-chain.pem": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURKekNDQWcrZ0F3SUJBZ0lRSzZFK3FQVGpGRjM5TVRaU2FYSU1HekFOQmdrcWhraUc5dzBCQVFzRkFEQVkKTVJZd0ZBWURWUVFLRXcxamJIVnpkR1Z5TG14dlkyRnNNQjRYRFRJeE1ERXlNVEF4TURneU5Wb1hEVEl4TURReQpNVEF4TURneU5Wb3dBRENDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFPWkZqazZWCkgxY1RoM1ZEdGowZy9rMWticnJadzQ3NHN1SkduSlJFVDArK1FBa1BDdE1sRzJOYVNENTByQWNFdTBBSlZzaXAKTmM0NTZkRlVzdk1IYVErQWhZYURQTDdHa3c2eDRyVVBRQkQwa3lYQUhjenUrY3FhZklXdGcrTGZibDhYYVZHTQpQMk5HVEJ1aEhtQVV0V0VORVB4NW1jaUlVOWpDZXQ0Szh0ZDFZQ2FtS1hSak1ldFBrR3ZrRDBGdGQ0WTVNSVNyCnNyNjdVdE9rWmgvTEpEWnFJVlBqa0JWdEJnQXdZNGdFRTV5SUdna3lNaVlreE9xL1JMOGxQejN2WVA5ci85aEMKQUtWVTJTSGxrNGFMa3VmVzJWaTdzSTJpRnZIYzgxeVJ6VE5UYkVFWkY2MUxFQm1MNzVIamdTbVN5R0poZTBQcwpzYWJQTzk2RDJOTkFNbjhDQXdFQUFhT0JoRENCZ1RBT0JnTlZIUThCQWY4RUJBTUNCYUF3SFFZRFZSMGxCQll3CkZBWUlLd1lCQlFVSEF3RUdDQ3NHQVFVRkJ3TUNNQXdHQTFVZEV3RUIvd1FDTUFBd1FnWURWUjBSQVFIL0JEZ3cKTm9ZMGMzQnBabVpsT2k4dlkyeDFjM1JsY2k1c2IyTmhiQzl1Y3k5a1pXWmhkV3gwTDNOaEwycGhaV2RsY2kxdgpjR1Z5WVhSdmNqQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFDYXFzY09QNXJnMm96ZmlpckdEWmx2dUFWOFZJCmR6ZUxEaTlMMHpLVjBxLy9TQW5SUEl5bWk0ampDYkRkbmYvYnpWWEdnZVNUNTNTeUR4Z3ZXVkQ2akZzK0JwTlcKcXFFWWE0NWdLUEFreUVpaVJJbW0vRFBQSzk4T2FKbGROK2xpVDllU1o1SUFocCtvVml5WnVwZURTR3cvTXdIdwphQ3dPbjYwSDdrUEU3cTY3NlZLU2tXd1BtdWpQU0xqeE5UWXhQVklPblZsVmo4REZwNUM4LzZGM3VUb1J6Qm1aCmM2Znhvblo1UWdreDBWRHl4R3lMU0w2UXRudFBXdkpha0RsZFphek4zUlM2ZnFqZ0dFa01FUWQwdjhGcEh3RTQKZmRJbTNMYksvWWtWSXkwZ0l1TGYzVklKNkxBcjdCWW11ODE3dGxjRExud3FIZUVFL1Z3cGxvWHpWZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K",
"root-cert.pem": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMzVENDQWNXZ0F3SUJBZ0lRUWlNTDcvcFoyV0hMWVZRMGFIelpMREFOQmdrcWhraUc5dzBCQVFzRkFEQVkKTVJZd0ZBWURWUVFLRXcxamJIVnpkR1Z5TG14dlkyRnNNQjRYRFRJeE1ERXlNVEF4TURZek1Gb1hEVE14TURFeApPVEF4TURZek1Gb3dHREVXTUJRR0ExVUVDaE1OWTJ4MWMzUmxjaTVzYjJOaGJEQ0NBU0l3RFFZSktvWklodmNOCkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFLZGJpM0JYZ0FkcElYcDVCaThYdWMxVWhZei91SmtXYkxBODRxRTAKdmtHQ3R6N3cycFltUEJ2dmdvUzZzdyt2MGlHcFdsZllGdDQ0U1p1V1M4Um5SR2QzeXhtK09oWmFab1c0eFI2bwpRdE9wRTFUMnc3QUVFeTVKY2MvUkdjTHBiWXpPUFdCamtXU01YSmZoeEJSeTZZL3J3dUJMVjBrRjNlZnF5cUVUCklUcUxaWVYxYS9BYzhGcGVkcnlieVFBSHRzcWdnTUNMN250VlgrMUZwdUg5QVhmRGxpV0tTNnJ1T2tPUEMrY1IKY3l2ZkUyRmlINmMyZkVqeU5WMTU3cEc1UHliQTFsaGdMUVVXSUsxZ1FBTGg1Um9IVE1BUDFYakt3S2FWeDBRVApSeDhpaWlhZnVvdHEyZ3Q2NDRtL2ZmRndRUmVKVTcwLytrV2h6NXBsNGQrVVQzOENBd0VBQWFNak1DRXdEZ1lEClZSMFBBUUgvQkFRREFnSUVNQThHQTFVZEV3RUIvd1FGTUFNQkFmOHdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUIKQUtCcDdxS1MrNENhb29naCtiVmVmOWoyaFRLOFVPRDNWSzFuQXFLRllZcCtvU3l4dzI2bGNmcWpBVXlBYmp2RQpUSEtQaHhaL3NtbVd1RGU0SWI0YTAvNi9RaWRqemJSMTVCOWlwWTFESExqUGU4anJMMm1uSjd0YzBSYnM0ZFVrCjVIV0VXbzRDZXM0SFUwajVFVGdycHdUY2J5VXYyVTRXNjA1WTRMRnJCNVJWOS9wSkRyKzhtb1FhdWhEZEpTTHIKaW1yZ0xyVmRxZHRTOTl6dDdVRTRsZ3ovckpKV1h6eSs4S1dZRjh5RXUxSjVnNUhMR25ubXJZbjRGUUFEZW1iSQp3bnBvc1FObm5XUnZqSXZlRDE3dDNnOHFSbFhDa1krZGM4VGJKT2lEZ1JUOC9yUlo3REpiMjlsQlp0NkpkOE10CjRCZzNSaDllTVBhWHFIZUdlckhHMzgwPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg=="
},
"kind": "Secret",
"metadata": {
"annotations": {
"istio.io/service-account.name": "jaeger-operator"
},
"creationTimestamp": "2021-01-21T01:08:25Z",
"managedFields": [
{
"apiVersion": "v1",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:data": {
".": {},
"f:cert-chain.pem": {},
"f:key.pem": {},
"f:root-cert.pem": {}
},
"f:metadata": {
"f:annotations": {
".": {},
"f:istio.io/service-account.name": {}
}
},
"f:type": {}
},
"manager": "istio_ca",
"operation": "Update",
"time": "2021-01-21T01:08:25Z"
}
],
"name": "istio.jaeger-operator",
"namespace": "default",
"resourceVersion": "451570",
"selfLink": "/api/v1/namespaces/default/secrets/istio.jaeger-operator",
"uid": "fb60f655-6b24-4f35-8e2d-17d7ca3ba7d4"
},
"type": "istio.io/key-and-cert"
}

View File

@ -0,0 +1,66 @@
{
"apiVersion": "v1",
"kind": "ServiceAccount",
"metadata": {
"annotations": {
"kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"ServiceAccount\",\"metadata\":{\"annotations\":{},\"labels\":{\"app\":\"istio-ingressgateway\",\"chart\":\"gateways\",\"heritage\":\"Tiller\",\"release\":\"istio\"},\"name\":\"istio-ingressgateway-service-account\",\"namespace\":\"istio-system\"}}\n"
},
"creationTimestamp": "2021-01-21T01:05:43Z",
"labels": {
"app": "istio-ingressgateway",
"chart": "gateways",
"heritage": "Tiller",
"release": "istio"
},
"managedFields": [
{
"apiVersion": "v1",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:secrets": {
".": {},
"k:{\"name\":\"istio-ingressgateway-service-account-token-zmk8b\"}": {
".": {},
"f:name": {}
}
}
},
"manager": "kube-controller-manager",
"operation": "Update",
"time": "2021-01-21T01:05:43Z"
},
{
"apiVersion": "v1",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:metadata": {
"f:annotations": {
".": {},
"f:kubectl.kubernetes.io/last-applied-configuration": {}
},
"f:labels": {
".": {},
"f:app": {},
"f:chart": {},
"f:heritage": {},
"f:release": {}
}
}
},
"manager": "kubectl-client-side-apply",
"operation": "Update",
"time": "2021-01-21T01:05:43Z"
}
],
"name": "istio-ingressgateway-service-account",
"namespace": "istio-system",
"resourceVersion": "450491",
"selfLink": "/api/v1/namespaces/istio-system/serviceaccounts/istio-ingressgateway-service-account",
"uid": "de09c78a-ea26-42ff-82d5-2f7d3f24a8d1"
},
"secrets": [
{
"name": "istio-ingressgateway-service-account-token-zmk8b"
}
]
}

View File

@ -0,0 +1,94 @@
{
"apiVersion": "v1",
"kind": "Service",
"metadata": {
"creationTimestamp": "2021-01-21T01:08:52Z",
"labels": {
"name": "jaeger-operator"
},
"managedFields": [
{
"apiVersion": "v1",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:metadata": {
"f:labels": {
".": {},
"f:name": {}
},
"f:ownerReferences": {
".": {},
"k:{\"uid\":\"baa856ea-2d04-4bbb-b9be-aa5b89c58087\"}": {
".": {},
"f:apiVersion": {},
"f:blockOwnerDeletion": {},
"f:controller": {},
"f:kind": {},
"f:name": {},
"f:uid": {}
}
}
},
"f:spec": {
"f:ports": {
".": {},
"k:{\"port\":8383,\"protocol\":\"TCP\"}": {
".": {},
"f:name": {},
"f:port": {},
"f:protocol": {},
"f:targetPort": {}
}
},
"f:selector": {
".": {},
"f:name": {}
},
"f:sessionAffinity": {},
"f:type": {}
}
},
"manager": "jaeger-operator",
"operation": "Update",
"time": "2021-01-21T01:08:52Z"
}
],
"name": "jaeger-operator",
"namespace": "default",
"ownerReferences": [
{
"apiVersion": "apps/v1",
"blockOwnerDeletion": true,
"controller": true,
"kind": "Deployment",
"name": "jaeger-operator",
"uid": "baa856ea-2d04-4bbb-b9be-aa5b89c58087"
}
],
"resourceVersion": "451805",
"selfLink": "/api/v1/namespaces/default/services/jaeger-operator",
"uid": "d8dfda88-e2c5-479e-bb2d-d0964805a925"
},
"spec": {
"clusterIP": "10.152.183.187",
"clusterIPs": [
"10.152.183.187"
],
"ports": [
{
"name": "metrics",
"port": 8383,
"protocol": "TCP",
"targetPort": 8383
}
],
"selector": {
"name": "jaeger-operator"
},
"sessionAffinity": "None",
"type": "ClusterIP"
},
"status": {
"loadBalancer": {}
}
}

Some files were not shown because too many files have changed in this diff Show More