diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-16 18:50:48 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-16 18:50:48 +0000 |
commit | 692eeae1b1cbb8abf0fe81c9bdad936755bd07c5 (patch) | |
tree | 3bccb791a4f778db2e6439165a24c384e489ca2b | |
parent | Adding upstream version 1.2.5+ds1. (diff) | |
download | golang-github-openshift-imagebuilder-692eeae1b1cbb8abf0fe81c9bdad936755bd07c5.tar.xz golang-github-openshift-imagebuilder-692eeae1b1cbb8abf0fe81c9bdad936755bd07c5.zip |
Adding debian version 1.2.5+ds1-3.debian/1.2.5+ds1-3debian
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
-rw-r--r-- | debian/changelog | 101 | ||||
-rw-r--r-- | debian/control | 77 | ||||
-rw-r--r-- | debian/copyright | 31 | ||||
-rw-r--r-- | debian/gbp.conf | 2 | ||||
-rw-r--r-- | debian/gitlab-ci.yml | 6 | ||||
-rw-r--r-- | debian/golang-github-openshift-imagebuilder-dev.docs | 3 | ||||
-rw-r--r-- | debian/golang-github-openshift-imagebuilder-dev.install | 1 | ||||
-rw-r--r-- | debian/golang-github-openshift-imagebuilder-dev.lintian-override | 2 | ||||
-rw-r--r-- | debian/license-reconcile.yml | 6 | ||||
-rw-r--r-- | debian/openshift-imagebuilder.docs | 3 | ||||
-rw-r--r-- | debian/openshift-imagebuilder.install | 1 | ||||
-rw-r--r-- | debian/patches/ftbfs-arm.patch | 18 | ||||
-rw-r--r-- | debian/patches/ignore-arch-tests.patch | 12 | ||||
-rw-r--r-- | debian/patches/klog.patch | 1672 | ||||
-rw-r--r-- | debian/patches/series | 3 | ||||
-rwxr-xr-x | debian/rules | 13 | ||||
-rw-r--r-- | debian/source/format | 1 | ||||
-rw-r--r-- | debian/source/lintian-overrides | 2 | ||||
-rw-r--r-- | debian/upstream/metadata | 5 | ||||
-rw-r--r-- | debian/watch | 10 |
20 files changed, 1969 insertions, 0 deletions
diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..858f42e --- /dev/null +++ b/debian/changelog @@ -0,0 +1,101 @@ +golang-github-openshift-imagebuilder (1.2.5+ds1-3) unstable; urgency=medium + + * Upload to unstable + + -- Reinhard Tartler <siretart@tauware.de> Sat, 09 Sep 2023 11:15:34 -0400 + +golang-github-openshift-imagebuilder (1.2.5+ds1-2) experimental; urgency=medium + + * fix FTBFS on ARM archs, disable broken test + + -- Reinhard Tartler <siretart@tauware.de> Sat, 02 Sep 2023 21:07:09 -0400 + +golang-github-openshift-imagebuilder (1.2.5+ds1-1) experimental; urgency=medium + + * New upstream version + * Add lintian overrides for funny test data + * Bump standards version + * Tighten dependency on containers/storage + + -- Reinhard Tartler <siretart@tauware.de> Sat, 02 Sep 2023 08:38:00 -0400 + +golang-github-openshift-imagebuilder (1.2.3+ds1-2) unstable; urgency=medium + + * Bug fix: "golang-github-openshift-imagebuilder FTBFS due to unlisted + dependency", thanks to William Wilson (Closes: #1014183). + + -- Reinhard Tartler <siretart@tauware.de> Sun, 10 Jul 2022 07:11:52 -0400 + +golang-github-openshift-imagebuilder (1.2.3+ds1-1) unstable; urgency=medium + + * New upstream release + + -- Reinhard Tartler <siretart@tauware.de> Wed, 18 May 2022 22:04:00 -0400 + +golang-github-openshift-imagebuilder (1.2.1+ds1-3) unstable; urgency=medium + + * Upload to unstable + * Bug fix: "Typo in package description", thanks to George B. (Closes: + #947240). + + -- Reinhard Tartler <siretart@tauware.de> Sun, 29 Aug 2021 11:02:07 +0200 + +golang-github-openshift-imagebuilder (1.2.1+ds1-2) experimental; urgency=medium + + * Depend explicitly on golang-github-opencontainers-image-spec-dev + + -- Reinhard Tartler <siretart@tauware.de> Sat, 12 Jun 2021 07:15:07 -0400 + +golang-github-openshift-imagebuilder (1.2.1+ds1-1) experimental; urgency=medium + + * New upstream release + * Backport upstream patch: Add mounts to dispatch run + + -- Reinhard Tartler <siretart@tauware.de> Mon, 07 Jun 2021 17:50:25 -0400 + +golang-github-openshift-imagebuilder (1.2.0+ds1-1) experimental; urgency=medium + + * New upstream release + * Bump debhelper from old 11 to 12. + * Set debhelper-compat version in Build-Depends. + * Set upstream metadata fields: Bug-Database, Bug-Submit, Repository, + Repository-Browse. + + -- Reinhard Tartler <siretart@tauware.de> Fri, 02 Apr 2021 21:14:04 -0400 + +golang-github-openshift-imagebuilder (1.1.6-2) unstable; urgency=medium + + * debian/control: depend on golang-github-containerd-containerd-dev + + -- Reinhard Tartler <siretart@tauware.de> Fri, 24 Jul 2020 07:20:05 -0400 + +golang-github-openshift-imagebuilder (1.1.6-1) unstable; urgency=medium + + * New upstream version 1.1.6 + + -- Reinhard Tartler <siretart@tauware.de> Sat, 11 Jul 2020 11:57:26 -0400 + +golang-github-openshift-imagebuilder (1.1.4-2) unstable; urgency=medium + + * Fix FTBFS on arm platforms (Closes: #959538) + + -- Reinhard Tartler <siretart@tauware.de> Tue, 19 May 2020 06:51:27 -0400 + +golang-github-openshift-imagebuilder (1.1.4-1) unstable; urgency=medium + + * New upstream version 1.1.4 + * vendor k8s.io/klog + + -- Reinhard Tartler <siretart@tauware.de> Sun, 26 Apr 2020 13:52:45 -0400 + +golang-github-openshift-imagebuilder (1.1.0-2) unstable; urgency=medium + + * Upload to unstable + + -- Reinhard Tartler <siretart@tauware.de> Sat, 19 Oct 2019 11:17:37 -0400 + +golang-github-openshift-imagebuilder (1.1.0-1) experimental; urgency=medium + + * Initial release (Closes: #923300) + + -- Reinhard Tartler <siretart@tauware.de> Wed, 10 Apr 2019 21:27:11 -0400 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..b37f57f --- /dev/null +++ b/debian/control @@ -0,0 +1,77 @@ +Source: golang-github-openshift-imagebuilder +Section: devel +Priority: optional +Maintainer: Debian Go Packaging Team <team+pkg-go@tracker.debian.org> +Uploaders: Reinhard Tartler <siretart@tauware.de> +Build-Depends: debhelper-compat (= 12), + dh-golang, + golang-any, + golang-github-containerd-containerd-dev, + golang-github-containers-storage-dev (>= 1.46), + golang-github-docker-distribution-dev, + golang-github-docker-docker-dev (>= 18.09.3+dfsg1), + golang-github-fsouza-go-dockerclient-dev, + golang-github-opencontainers-image-spec-dev, + golang-github-ulikunitz-xz-dev, + golang-glog-dev, + golang-google-genproto-dev, + golang-google-grpc-dev, +Standards-Version: 4.6.2 +Homepage: https://github.com/openshift/imagebuilder +Vcs-Browser: https://salsa.debian.org/go-team/packages/golang-github-openshift-imagebuilder +Vcs-Git: https://salsa.debian.org/go-team/packages/golang-github-openshift-imagebuilder.git +XS-Go-Import-Path: github.com/openshift/imagebuilder +Testsuite: autopkgtest-pkg-go + +Package: openshift-imagebuilder +Architecture: any +Built-Using: ${misc:Built-Using} +Depends: ${misc:Depends}, + ${shlibs:Depends} +Description: Builds container images using Dockerfile as input + This package supports using the Dockerfile syntax to build OCI & Docker + compatible images, without invoking a container build command such + as buildah bud or docker build. It is intended to give clients more + control over how they build container images, including: + - Instead of building one layer per line, run all instructions in the + same container + - Set HostConfig settings like network and memory controls that are + not available when running container builds + - Mount external files into the build that are not persisted as part + of the final image (i.e. "secrets") + - If there are no RUN commands in the Dockerfile, the container is + created and committed, but never started. The final image should be + 99.9% compatible with regular container builds, but bugs are always + possible. + . + This package provides the imagebuilder command-line utility. + +Package: golang-github-openshift-imagebuilder-dev +Architecture: all +Depends: ${misc:Depends}, + golang-github-containerd-containerd-dev, + golang-github-containers-storage-dev (>> 1.46), + golang-github-docker-distribution-dev, + golang-github-docker-docker-dev (>> 18.09.3+dfsg1), + golang-github-fsouza-go-dockerclient-dev, + golang-github-opencontainers-image-spec-dev, + golang-github-ulikunitz-xz-dev, + golang-glog-dev +Description: Builds container images using Dockerfile as input + This library supports using the Dockerfile syntax to build OCI & Docker + compatible images, without invoking a container build command such + as buildah bud or docker build. It is intended to give clients more + control over how they build container images, including: + - Instead of building one layer per line, run all instructions in the + same container + - Set HostConfig settings like network and memory controls that are + not available when running container builds + - Mount external files into the build that are not persisted as part + of the final image (i.e. "secrets") + - If there are no RUN commands in the Dockerfile, the container is + created and committed, but never started. The final image should be + 99.9% compatible with regular container builds, but bugs are always + possible. + . + This package provides sources that other package may require for + building. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..c53bebf --- /dev/null +++ b/debian/copyright @@ -0,0 +1,31 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: imagebuilder +Source: https://github.com/openshift/imagebuilder +Files-Excluded: + vendor + +Files: * +Copyright: 2016-2019 OpenShift + 2017-2019 RedHat +License: Apache-2.0 + +Files: debian/* +Copyright: 2019 Reinhard Tartler <siretart@tauware.de> +License: Apache-2.0 +Comment: Debian packaging is licensed under the same terms as upstream + +License: Apache-2.0 + 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. + . + On Debian systems, the complete text of the Apache version 2.0 license + can be found in "/usr/share/common-licenses/Apache-2.0". diff --git a/debian/gbp.conf b/debian/gbp.conf new file mode 100644 index 0000000..cec628c --- /dev/null +++ b/debian/gbp.conf @@ -0,0 +1,2 @@ +[DEFAULT] +pristine-tar = True diff --git a/debian/gitlab-ci.yml b/debian/gitlab-ci.yml new file mode 100644 index 0000000..594e14e --- /dev/null +++ b/debian/gitlab-ci.yml @@ -0,0 +1,6 @@ +# auto-generated, DO NOT MODIFY. +# The authoritative copy of this file lives at: +# https://salsa.debian.org/go-team/infra/pkg-go-tools/blob/master/config/gitlabciyml.go +--- +include: + - https://salsa.debian.org/go-team/infra/pkg-go-tools/-/raw/master/pipeline/test-archive.yml diff --git a/debian/golang-github-openshift-imagebuilder-dev.docs b/debian/golang-github-openshift-imagebuilder-dev.docs new file mode 100644 index 0000000..9db21b7 --- /dev/null +++ b/debian/golang-github-openshift-imagebuilder-dev.docs @@ -0,0 +1,3 @@ +LICENSE +README.md +dockerfile/NOTICE diff --git a/debian/golang-github-openshift-imagebuilder-dev.install b/debian/golang-github-openshift-imagebuilder-dev.install new file mode 100644 index 0000000..dd222db --- /dev/null +++ b/debian/golang-github-openshift-imagebuilder-dev.install @@ -0,0 +1 @@ +usr/share diff --git a/debian/golang-github-openshift-imagebuilder-dev.lintian-override b/debian/golang-github-openshift-imagebuilder-dev.lintian-override new file mode 100644 index 0000000..8a9f7d6 --- /dev/null +++ b/debian/golang-github-openshift-imagebuilder-dev.lintian-override @@ -0,0 +1,2 @@ +# contains testdata that is not really an .a archive +golang-github-openshift-imagebuilder-dev: unpack-message-for-deb-data diff --git a/debian/license-reconcile.yml b/debian/license-reconcile.yml new file mode 100644 index 0000000..f86288e --- /dev/null +++ b/debian/license-reconcile.yml @@ -0,0 +1,6 @@ +Rules: + rules: + - + Glob: debian/* + License: Apache-2.0 + Copyright: Reinhard Tartler <siretart@tauware.de> diff --git a/debian/openshift-imagebuilder.docs b/debian/openshift-imagebuilder.docs new file mode 100644 index 0000000..9db21b7 --- /dev/null +++ b/debian/openshift-imagebuilder.docs @@ -0,0 +1,3 @@ +LICENSE +README.md +dockerfile/NOTICE diff --git a/debian/openshift-imagebuilder.install b/debian/openshift-imagebuilder.install new file mode 100644 index 0000000..e772481 --- /dev/null +++ b/debian/openshift-imagebuilder.install @@ -0,0 +1 @@ +usr/bin diff --git a/debian/patches/ftbfs-arm.patch b/debian/patches/ftbfs-arm.patch new file mode 100644 index 0000000..7808d4f --- /dev/null +++ b/debian/patches/ftbfs-arm.patch @@ -0,0 +1,18 @@ +From: Reinhard Tartler <siretart@tauware.de> +Description: Fix FTBFS on arm platforms +Forwarded: https://github.com/openshift/imagebuilder/issues/160 +Bug-Debian: http://bugs.debian.org/959538 + +diff --git a/dispatchers_test.go b/dispatchers_test.go +index dc46c96..718a9a4 100644 +--- a/dispatchers_test.go ++++ b/dispatchers_test.go +@@ -23,7 +23,7 @@ func TestDispatchArgDefaultBuiltins(t *testing.T) { + localspec := platforms.DefaultSpec() + expectedArgs := []string{ + "BUILDARCH=" + localspec.Architecture, +- "TARGETPLATFORM=" + localspec.OS + "/" + localspec.Architecture, ++ "TARGETPLATFORM=" + platforms.DefaultString(), + } + got := mybuilder.Arguments() + sort.Strings(got) diff --git a/debian/patches/ignore-arch-tests.patch b/debian/patches/ignore-arch-tests.patch new file mode 100644 index 0000000..69b7cce --- /dev/null +++ b/debian/patches/ignore-arch-tests.patch @@ -0,0 +1,12 @@ +Index: golang-github-openshift-imagebuilder/dispatchers_test.go +=================================================================== +--- golang-github-openshift-imagebuilder.orig/dispatchers_test.go ++++ golang-github-openshift-imagebuilder/dispatchers_test.go +@@ -777,6 +777,7 @@ func TestDispatchFromFlags(t *testing.T) + } + + func TestDispatchFromFlagsAndUseBuiltInArgs(t *testing.T) { ++ t.Skip("DM-skipped, cf. https://github.com/openshift/imagebuilder/pull/224#issuecomment-1703977008") + expectedPlatform := localspec.OS + "/" + localspec.Architecture + mybuilder := Builder{ + RunConfig: docker.Config{ diff --git a/debian/patches/klog.patch b/debian/patches/klog.patch new file mode 100644 index 0000000..cb825b7 --- /dev/null +++ b/debian/patches/klog.patch @@ -0,0 +1,1672 @@ +diff --git a/vendor/k8s.io/klog/LICENSE b/vendor/k8s.io/klog/LICENSE +new file mode 100644 +index 0000000..37ec93a +--- /dev/null ++++ b/vendor/k8s.io/klog/LICENSE +@@ -0,0 +1,191 @@ ++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: ++ ++You must give any other recipients of the Work or Derivative Works a copy of ++this License; and ++You must cause any modified files to carry prominent notices stating that You ++changed the files; and ++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 ++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. +diff --git a/vendor/k8s.io/klog/README.md b/vendor/k8s.io/klog/README.md +new file mode 100644 +index 0000000..6cb6d16 +--- /dev/null ++++ b/vendor/k8s.io/klog/README.md +@@ -0,0 +1,77 @@ ++klog ++==== ++ ++klog is a permanant fork of https://github.com/golang/glog. original README from glog is below ++ ++---- ++ ++How to use klog ++=============== ++- Replace imports for `github.com/golang/glog` with `k8s.io/klog` ++- Use `klog.InitFlags(nil)` explicitly for initializing global flags as we no longer use `init()` method to register the flags ++- You can now use `log-file` instead of `log-dir` for logging to a single file (See `examples/log_file/usage_log_file.go`) ++- If you want to redirect everything logged using klog somewhere else (say syslog!), you can use `klog.SetOutput()` method and supply a `io.Writer`. (See `examples/set_output/usage_set_output.go`) ++- For more logging conventions (See [Logging Conventions](https://github.com/kubernetes/community/blob/master/contributors/devel/logging.md)) ++ ++### Coexisting with glog ++This package can be used side by side with glog. [This example](examples/coexist_glog/coexist_glog.go) shows how to initialize and syncronize flags from the global `flag.CommandLine` FlagSet. In addition, the example makes use of stderr as combined output by setting `alsologtostderr` (or `logtostderr`) to `true`. ++ ++## Community, discussion, contribution, and support ++ ++Learn how to engage with the Kubernetes community on the [community page](http://kubernetes.io/community/). ++ ++You can reach the maintainers of this project at: ++ ++- [Slack](https://kubernetes.slack.com/messages/sig-architecture) ++- [Mailing List](https://groups.google.com/forum/#!forum/kubernetes-sig-architecture) ++ ++### Code of conduct ++ ++Participation in the Kubernetes community is governed by the [Kubernetes Code of Conduct](code-of-conduct.md). ++ ++---- ++ ++glog ++==== ++ ++Leveled execution logs for Go. ++ ++This is an efficient pure Go implementation of leveled logs in the ++manner of the open source C++ package ++ https://github.com/google/glog ++ ++By binding methods to booleans it is possible to use the log package ++without paying the expense of evaluating the arguments to the log. ++Through the -vmodule flag, the package also provides fine-grained ++control over logging at the file level. ++ ++The comment from glog.go introduces the ideas: ++ ++ Package glog implements logging analogous to the Google-internal ++ C++ INFO/ERROR/V setup. It provides functions Info, Warning, ++ Error, Fatal, plus formatting variants such as Infof. It ++ also provides V-style logging controlled by the -v and ++ -vmodule=file=2 flags. ++ ++ Basic examples: ++ ++ glog.Info("Prepare to repel boarders") ++ ++ glog.Fatalf("Initialization failed: %s", err) ++ ++ See the documentation for the V function for an explanation ++ of these examples: ++ ++ if glog.V(2) { ++ glog.Info("Starting transaction...") ++ } ++ ++ glog.V(2).Infoln("Processed", nItems, "elements") ++ ++ ++The repository contains an open source version of the log package ++used inside Google. The master copy of the source lives inside ++Google, not here. The code in this repo is for export only and is not itself ++under development. Feature requests will be ignored. ++ ++Send bug reports to golang-nuts@googlegroups.com. +diff --git a/vendor/k8s.io/klog/klog.go b/vendor/k8s.io/klog/klog.go +new file mode 100644 +index 0000000..398cd1c +--- /dev/null ++++ b/vendor/k8s.io/klog/klog.go +@@ -0,0 +1,1241 @@ ++// Go support for leveled logs, analogous to https://code.google.com/p/google-glog/ ++// ++// Copyright 2013 Google Inc. All Rights Reserved. ++// ++// 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. ++ ++// Package klog implements logging analogous to the Google-internal C++ INFO/ERROR/V setup. ++// It provides functions Info, Warning, Error, Fatal, plus formatting variants such as ++// Infof. It also provides V-style logging controlled by the -v and -vmodule=file=2 flags. ++// ++// Basic examples: ++// ++// glog.Info("Prepare to repel boarders") ++// ++// glog.Fatalf("Initialization failed: %s", err) ++// ++// See the documentation for the V function for an explanation of these examples: ++// ++// if glog.V(2) { ++// glog.Info("Starting transaction...") ++// } ++// ++// glog.V(2).Infoln("Processed", nItems, "elements") ++// ++// Log output is buffered and written periodically using Flush. Programs ++// should call Flush before exiting to guarantee all log output is written. ++// ++// By default, all log statements write to files in a temporary directory. ++// This package provides several flags that modify this behavior. ++// As a result, flag.Parse must be called before any logging is done. ++// ++// -logtostderr=false ++// Logs are written to standard error instead of to files. ++// -alsologtostderr=false ++// Logs are written to standard error as well as to files. ++// -stderrthreshold=ERROR ++// Log events at or above this severity are logged to standard ++// error as well as to files. ++// -log_dir="" ++// Log files will be written to this directory instead of the ++// default temporary directory. ++// ++// Other flags provide aids to debugging. ++// ++// -log_backtrace_at="" ++// When set to a file and line number holding a logging statement, ++// such as ++// -log_backtrace_at=gopherflakes.go:234 ++// a stack trace will be written to the Info log whenever execution ++// hits that statement. (Unlike with -vmodule, the ".go" must be ++// present.) ++// -v=0 ++// Enable V-leveled logging at the specified level. ++// -vmodule="" ++// The syntax of the argument is a comma-separated list of pattern=N, ++// where pattern is a literal file name (minus the ".go" suffix) or ++// "glob" pattern and N is a V level. For instance, ++// -vmodule=gopher*=3 ++// sets the V level to 3 in all Go files whose names begin "gopher". ++// ++package klog ++ ++import ( ++ "bufio" ++ "bytes" ++ "errors" ++ "flag" ++ "fmt" ++ "io" ++ stdLog "log" ++ "os" ++ "path/filepath" ++ "runtime" ++ "strconv" ++ "strings" ++ "sync" ++ "sync/atomic" ++ "time" ++) ++ ++// severity identifies the sort of log: info, warning etc. It also implements ++// the flag.Value interface. The -stderrthreshold flag is of type severity and ++// should be modified only through the flag.Value interface. The values match ++// the corresponding constants in C++. ++type severity int32 // sync/atomic int32 ++ ++// These constants identify the log levels in order of increasing severity. ++// A message written to a high-severity log file is also written to each ++// lower-severity log file. ++const ( ++ infoLog severity = iota ++ warningLog ++ errorLog ++ fatalLog ++ numSeverity = 4 ++) ++ ++const severityChar = "IWEF" ++ ++var severityName = []string{ ++ infoLog: "INFO", ++ warningLog: "WARNING", ++ errorLog: "ERROR", ++ fatalLog: "FATAL", ++} ++ ++// get returns the value of the severity. ++func (s *severity) get() severity { ++ return severity(atomic.LoadInt32((*int32)(s))) ++} ++ ++// set sets the value of the severity. ++func (s *severity) set(val severity) { ++ atomic.StoreInt32((*int32)(s), int32(val)) ++} ++ ++// String is part of the flag.Value interface. ++func (s *severity) String() string { ++ return strconv.FormatInt(int64(*s), 10) ++} ++ ++// Get is part of the flag.Value interface. ++func (s *severity) Get() interface{} { ++ return *s ++} ++ ++// Set is part of the flag.Value interface. ++func (s *severity) Set(value string) error { ++ var threshold severity ++ // Is it a known name? ++ if v, ok := severityByName(value); ok { ++ threshold = v ++ } else { ++ v, err := strconv.Atoi(value) ++ if err != nil { ++ return err ++ } ++ threshold = severity(v) ++ } ++ logging.stderrThreshold.set(threshold) ++ return nil ++} ++ ++func severityByName(s string) (severity, bool) { ++ s = strings.ToUpper(s) ++ for i, name := range severityName { ++ if name == s { ++ return severity(i), true ++ } ++ } ++ return 0, false ++} ++ ++// OutputStats tracks the number of output lines and bytes written. ++type OutputStats struct { ++ lines int64 ++ bytes int64 ++} ++ ++// Lines returns the number of lines written. ++func (s *OutputStats) Lines() int64 { ++ return atomic.LoadInt64(&s.lines) ++} ++ ++// Bytes returns the number of bytes written. ++func (s *OutputStats) Bytes() int64 { ++ return atomic.LoadInt64(&s.bytes) ++} ++ ++// Stats tracks the number of lines of output and number of bytes ++// per severity level. Values must be read with atomic.LoadInt64. ++var Stats struct { ++ Info, Warning, Error OutputStats ++} ++ ++var severityStats = [numSeverity]*OutputStats{ ++ infoLog: &Stats.Info, ++ warningLog: &Stats.Warning, ++ errorLog: &Stats.Error, ++} ++ ++// Level is exported because it appears in the arguments to V and is ++// the type of the v flag, which can be set programmatically. ++// It's a distinct type because we want to discriminate it from logType. ++// Variables of type level are only changed under logging.mu. ++// The -v flag is read only with atomic ops, so the state of the logging ++// module is consistent. ++ ++// Level is treated as a sync/atomic int32. ++ ++// Level specifies a level of verbosity for V logs. *Level implements ++// flag.Value; the -v flag is of type Level and should be modified ++// only through the flag.Value interface. ++type Level int32 ++ ++// get returns the value of the Level. ++func (l *Level) get() Level { ++ return Level(atomic.LoadInt32((*int32)(l))) ++} ++ ++// set sets the value of the Level. ++func (l *Level) set(val Level) { ++ atomic.StoreInt32((*int32)(l), int32(val)) ++} ++ ++// String is part of the flag.Value interface. ++func (l *Level) String() string { ++ return strconv.FormatInt(int64(*l), 10) ++} ++ ++// Get is part of the flag.Value interface. ++func (l *Level) Get() interface{} { ++ return *l ++} ++ ++// Set is part of the flag.Value interface. ++func (l *Level) Set(value string) error { ++ v, err := strconv.Atoi(value) ++ if err != nil { ++ return err ++ } ++ logging.mu.Lock() ++ defer logging.mu.Unlock() ++ logging.setVState(Level(v), logging.vmodule.filter, false) ++ return nil ++} ++ ++// moduleSpec represents the setting of the -vmodule flag. ++type moduleSpec struct { ++ filter []modulePat ++} ++ ++// modulePat contains a filter for the -vmodule flag. ++// It holds a verbosity level and a file pattern to match. ++type modulePat struct { ++ pattern string ++ literal bool // The pattern is a literal string ++ level Level ++} ++ ++// match reports whether the file matches the pattern. It uses a string ++// comparison if the pattern contains no metacharacters. ++func (m *modulePat) match(file string) bool { ++ if m.literal { ++ return file == m.pattern ++ } ++ match, _ := filepath.Match(m.pattern, file) ++ return match ++} ++ ++func (m *moduleSpec) String() string { ++ // Lock because the type is not atomic. TODO: clean this up. ++ logging.mu.Lock() ++ defer logging.mu.Unlock() ++ var b bytes.Buffer ++ for i, f := range m.filter { ++ if i > 0 { ++ b.WriteRune(',') ++ } ++ fmt.Fprintf(&b, "%s=%d", f.pattern, f.level) ++ } ++ return b.String() ++} ++ ++// Get is part of the (Go 1.2) flag.Getter interface. It always returns nil for this flag type since the ++// struct is not exported. ++func (m *moduleSpec) Get() interface{} { ++ return nil ++} ++ ++var errVmoduleSyntax = errors.New("syntax error: expect comma-separated list of filename=N") ++ ++// Syntax: -vmodule=recordio=2,file=1,gfs*=3 ++func (m *moduleSpec) Set(value string) error { ++ var filter []modulePat ++ for _, pat := range strings.Split(value, ",") { ++ if len(pat) == 0 { ++ // Empty strings such as from a trailing comma can be ignored. ++ continue ++ } ++ patLev := strings.Split(pat, "=") ++ if len(patLev) != 2 || len(patLev[0]) == 0 || len(patLev[1]) == 0 { ++ return errVmoduleSyntax ++ } ++ pattern := patLev[0] ++ v, err := strconv.Atoi(patLev[1]) ++ if err != nil { ++ return errors.New("syntax error: expect comma-separated list of filename=N") ++ } ++ if v < 0 { ++ return errors.New("negative value for vmodule level") ++ } ++ if v == 0 { ++ continue // Ignore. It's harmless but no point in paying the overhead. ++ } ++ // TODO: check syntax of filter? ++ filter = append(filter, modulePat{pattern, isLiteral(pattern), Level(v)}) ++ } ++ logging.mu.Lock() ++ defer logging.mu.Unlock() ++ logging.setVState(logging.verbosity, filter, true) ++ return nil ++} ++ ++// isLiteral reports whether the pattern is a literal string, that is, has no metacharacters ++// that require filepath.Match to be called to match the pattern. ++func isLiteral(pattern string) bool { ++ return !strings.ContainsAny(pattern, `\*?[]`) ++} ++ ++// traceLocation represents the setting of the -log_backtrace_at flag. ++type traceLocation struct { ++ file string ++ line int ++} ++ ++// isSet reports whether the trace location has been specified. ++// logging.mu is held. ++func (t *traceLocation) isSet() bool { ++ return t.line > 0 ++} ++ ++// match reports whether the specified file and line matches the trace location. ++// The argument file name is the full path, not the basename specified in the flag. ++// logging.mu is held. ++func (t *traceLocation) match(file string, line int) bool { ++ if t.line != line { ++ return false ++ } ++ if i := strings.LastIndex(file, "/"); i >= 0 { ++ file = file[i+1:] ++ } ++ return t.file == file ++} ++ ++func (t *traceLocation) String() string { ++ // Lock because the type is not atomic. TODO: clean this up. ++ logging.mu.Lock() ++ defer logging.mu.Unlock() ++ return fmt.Sprintf("%s:%d", t.file, t.line) ++} ++ ++// Get is part of the (Go 1.2) flag.Getter interface. It always returns nil for this flag type since the ++// struct is not exported ++func (t *traceLocation) Get() interface{} { ++ return nil ++} ++ ++var errTraceSyntax = errors.New("syntax error: expect file.go:234") ++ ++// Syntax: -log_backtrace_at=gopherflakes.go:234 ++// Note that unlike vmodule the file extension is included here. ++func (t *traceLocation) Set(value string) error { ++ if value == "" { ++ // Unset. ++ t.line = 0 ++ t.file = "" ++ } ++ fields := strings.Split(value, ":") ++ if len(fields) != 2 { ++ return errTraceSyntax ++ } ++ file, line := fields[0], fields[1] ++ if !strings.Contains(file, ".") { ++ return errTraceSyntax ++ } ++ v, err := strconv.Atoi(line) ++ if err != nil { ++ return errTraceSyntax ++ } ++ if v <= 0 { ++ return errors.New("negative or zero value for level") ++ } ++ logging.mu.Lock() ++ defer logging.mu.Unlock() ++ t.line = v ++ t.file = file ++ return nil ++} ++ ++// flushSyncWriter is the interface satisfied by logging destinations. ++type flushSyncWriter interface { ++ Flush() error ++ Sync() error ++ io.Writer ++} ++ ++func init() { ++ // Default stderrThreshold is ERROR. ++ logging.stderrThreshold = errorLog ++ ++ logging.setVState(0, nil, false) ++ go logging.flushDaemon() ++} ++ ++// InitFlags is for explicitly initializing the flags ++func InitFlags(flagset *flag.FlagSet) { ++ if flagset == nil { ++ flagset = flag.CommandLine ++ } ++ flagset.StringVar(&logging.logDir, "log_dir", "", "If non-empty, write log files in this directory") ++ flagset.StringVar(&logging.logFile, "log_file", "", "If non-empty, use this log file") ++ flagset.BoolVar(&logging.toStderr, "logtostderr", true, "log to standard error instead of files") ++ flagset.BoolVar(&logging.alsoToStderr, "alsologtostderr", false, "log to standard error as well as files") ++ flagset.Var(&logging.verbosity, "v", "number for the log level verbosity") ++ flagset.BoolVar(&logging.skipHeaders, "skip_headers", false, "If true, avoid header prefixes in the log messages") ++ flagset.Var(&logging.stderrThreshold, "stderrthreshold", "logs at or above this threshold go to stderr") ++ flagset.Var(&logging.vmodule, "vmodule", "comma-separated list of pattern=N settings for file-filtered logging") ++ flagset.Var(&logging.traceLocation, "log_backtrace_at", "when logging hits line file:N, emit a stack trace") ++} ++ ++// Flush flushes all pending log I/O. ++func Flush() { ++ logging.lockAndFlushAll() ++} ++ ++// loggingT collects all the global state of the logging setup. ++type loggingT struct { ++ // Boolean flags. Not handled atomically because the flag.Value interface ++ // does not let us avoid the =true, and that shorthand is necessary for ++ // compatibility. TODO: does this matter enough to fix? Seems unlikely. ++ toStderr bool // The -logtostderr flag. ++ alsoToStderr bool // The -alsologtostderr flag. ++ ++ // Level flag. Handled atomically. ++ stderrThreshold severity // The -stderrthreshold flag. ++ ++ // freeList is a list of byte buffers, maintained under freeListMu. ++ freeList *buffer ++ // freeListMu maintains the free list. It is separate from the main mutex ++ // so buffers can be grabbed and printed to without holding the main lock, ++ // for better parallelization. ++ freeListMu sync.Mutex ++ ++ // mu protects the remaining elements of this structure and is ++ // used to synchronize logging. ++ mu sync.Mutex ++ // file holds writer for each of the log types. ++ file [numSeverity]flushSyncWriter ++ // pcs is used in V to avoid an allocation when computing the caller's PC. ++ pcs [1]uintptr ++ // vmap is a cache of the V Level for each V() call site, identified by PC. ++ // It is wiped whenever the vmodule flag changes state. ++ vmap map[uintptr]Level ++ // filterLength stores the length of the vmodule filter chain. If greater ++ // than zero, it means vmodule is enabled. It may be read safely ++ // using sync.LoadInt32, but is only modified under mu. ++ filterLength int32 ++ // traceLocation is the state of the -log_backtrace_at flag. ++ traceLocation traceLocation ++ // These flags are modified only under lock, although verbosity may be fetched ++ // safely using atomic.LoadInt32. ++ vmodule moduleSpec // The state of the -vmodule flag. ++ verbosity Level // V logging level, the value of the -v flag/ ++ ++ // If non-empty, overrides the choice of directory in which to write logs. ++ // See createLogDirs for the full list of possible destinations. ++ logDir string ++ ++ // If non-empty, specifies the path of the file to write logs. mutually exclusive ++ // with the log-dir option. ++ logFile string ++ ++ // If true, do not add the prefix headers, useful when used with SetOutput ++ skipHeaders bool ++} ++ ++// buffer holds a byte Buffer for reuse. The zero value is ready for use. ++type buffer struct { ++ bytes.Buffer ++ tmp [64]byte // temporary byte array for creating headers. ++ next *buffer ++} ++ ++var logging loggingT ++ ++// setVState sets a consistent state for V logging. ++// l.mu is held. ++func (l *loggingT) setVState(verbosity Level, filter []modulePat, setFilter bool) { ++ // Turn verbosity off so V will not fire while we are in transition. ++ logging.verbosity.set(0) ++ // Ditto for filter length. ++ atomic.StoreInt32(&logging.filterLength, 0) ++ ++ // Set the new filters and wipe the pc->Level map if the filter has changed. ++ if setFilter { ++ logging.vmodule.filter = filter ++ logging.vmap = make(map[uintptr]Level) ++ } ++ ++ // Things are consistent now, so enable filtering and verbosity. ++ // They are enabled in order opposite to that in V. ++ atomic.StoreInt32(&logging.filterLength, int32(len(filter))) ++ logging.verbosity.set(verbosity) ++} ++ ++// getBuffer returns a new, ready-to-use buffer. ++func (l *loggingT) getBuffer() *buffer { ++ l.freeListMu.Lock() ++ b := l.freeList ++ if b != nil { ++ l.freeList = b.next ++ } ++ l.freeListMu.Unlock() ++ if b == nil { ++ b = new(buffer) ++ } else { ++ b.next = nil ++ b.Reset() ++ } ++ return b ++} ++ ++// putBuffer returns a buffer to the free list. ++func (l *loggingT) putBuffer(b *buffer) { ++ if b.Len() >= 256 { ++ // Let big buffers die a natural death. ++ return ++ } ++ l.freeListMu.Lock() ++ b.next = l.freeList ++ l.freeList = b ++ l.freeListMu.Unlock() ++} ++ ++var timeNow = time.Now // Stubbed out for testing. ++ ++/* ++header formats a log header as defined by the C++ implementation. ++It returns a buffer containing the formatted header and the user's file and line number. ++The depth specifies how many stack frames above lives the source line to be identified in the log message. ++ ++Log lines have this form: ++ Lmmdd hh:mm:ss.uuuuuu threadid file:line] msg... ++where the fields are defined as follows: ++ L A single character, representing the log level (eg 'I' for INFO) ++ mm The month (zero padded; ie May is '05') ++ dd The day (zero padded) ++ hh:mm:ss.uuuuuu Time in hours, minutes and fractional seconds ++ threadid The space-padded thread ID as returned by GetTID() ++ file The file name ++ line The line number ++ msg The user-supplied message ++*/ ++func (l *loggingT) header(s severity, depth int) (*buffer, string, int) { ++ _, file, line, ok := runtime.Caller(3 + depth) ++ if !ok { ++ file = "???" ++ line = 1 ++ } else { ++ slash := strings.LastIndex(file, "/") ++ if slash >= 0 { ++ file = file[slash+1:] ++ } ++ } ++ return l.formatHeader(s, file, line), file, line ++} ++ ++// formatHeader formats a log header using the provided file name and line number. ++func (l *loggingT) formatHeader(s severity, file string, line int) *buffer { ++ now := timeNow() ++ if line < 0 { ++ line = 0 // not a real line number, but acceptable to someDigits ++ } ++ if s > fatalLog { ++ s = infoLog // for safety. ++ } ++ buf := l.getBuffer() ++ if l.skipHeaders { ++ return buf ++ } ++ ++ // Avoid Fprintf, for speed. The format is so simple that we can do it quickly by hand. ++ // It's worth about 3X. Fprintf is hard. ++ _, month, day := now.Date() ++ hour, minute, second := now.Clock() ++ // Lmmdd hh:mm:ss.uuuuuu threadid file:line] ++ buf.tmp[0] = severityChar[s] ++ buf.twoDigits(1, int(month)) ++ buf.twoDigits(3, day) ++ buf.tmp[5] = ' ' ++ buf.twoDigits(6, hour) ++ buf.tmp[8] = ':' ++ buf.twoDigits(9, minute) ++ buf.tmp[11] = ':' ++ buf.twoDigits(12, second) ++ buf.tmp[14] = '.' ++ buf.nDigits(6, 15, now.Nanosecond()/1000, '0') ++ buf.tmp[21] = ' ' ++ buf.nDigits(7, 22, pid, ' ') // TODO: should be TID ++ buf.tmp[29] = ' ' ++ buf.Write(buf.tmp[:30]) ++ buf.WriteString(file) ++ buf.tmp[0] = ':' ++ n := buf.someDigits(1, line) ++ buf.tmp[n+1] = ']' ++ buf.tmp[n+2] = ' ' ++ buf.Write(buf.tmp[:n+3]) ++ return buf ++} ++ ++// Some custom tiny helper functions to print the log header efficiently. ++ ++const digits = "0123456789" ++ ++// twoDigits formats a zero-prefixed two-digit integer at buf.tmp[i]. ++func (buf *buffer) twoDigits(i, d int) { ++ buf.tmp[i+1] = digits[d%10] ++ d /= 10 ++ buf.tmp[i] = digits[d%10] ++} ++ ++// nDigits formats an n-digit integer at buf.tmp[i], ++// padding with pad on the left. ++// It assumes d >= 0. ++func (buf *buffer) nDigits(n, i, d int, pad byte) { ++ j := n - 1 ++ for ; j >= 0 && d > 0; j-- { ++ buf.tmp[i+j] = digits[d%10] ++ d /= 10 ++ } ++ for ; j >= 0; j-- { ++ buf.tmp[i+j] = pad ++ } ++} ++ ++// someDigits formats a zero-prefixed variable-width integer at buf.tmp[i]. ++func (buf *buffer) someDigits(i, d int) int { ++ // Print into the top, then copy down. We know there's space for at least ++ // a 10-digit number. ++ j := len(buf.tmp) ++ for { ++ j-- ++ buf.tmp[j] = digits[d%10] ++ d /= 10 ++ if d == 0 { ++ break ++ } ++ } ++ return copy(buf.tmp[i:], buf.tmp[j:]) ++} ++ ++func (l *loggingT) println(s severity, args ...interface{}) { ++ buf, file, line := l.header(s, 0) ++ fmt.Fprintln(buf, args...) ++ l.output(s, buf, file, line, false) ++} ++ ++func (l *loggingT) print(s severity, args ...interface{}) { ++ l.printDepth(s, 1, args...) ++} ++ ++func (l *loggingT) printDepth(s severity, depth int, args ...interface{}) { ++ buf, file, line := l.header(s, depth) ++ fmt.Fprint(buf, args...) ++ if buf.Bytes()[buf.Len()-1] != '\n' { ++ buf.WriteByte('\n') ++ } ++ l.output(s, buf, file, line, false) ++} ++ ++func (l *loggingT) printf(s severity, format string, args ...interface{}) { ++ buf, file, line := l.header(s, 0) ++ fmt.Fprintf(buf, format, args...) ++ if buf.Bytes()[buf.Len()-1] != '\n' { ++ buf.WriteByte('\n') ++ } ++ l.output(s, buf, file, line, false) ++} ++ ++// printWithFileLine behaves like print but uses the provided file and line number. If ++// alsoLogToStderr is true, the log message always appears on standard error; it ++// will also appear in the log file unless --logtostderr is set. ++func (l *loggingT) printWithFileLine(s severity, file string, line int, alsoToStderr bool, args ...interface{}) { ++ buf := l.formatHeader(s, file, line) ++ fmt.Fprint(buf, args...) ++ if buf.Bytes()[buf.Len()-1] != '\n' { ++ buf.WriteByte('\n') ++ } ++ l.output(s, buf, file, line, alsoToStderr) ++} ++ ++// redirectBuffer is used to set an alternate destination for the logs ++type redirectBuffer struct { ++ w io.Writer ++} ++ ++func (rb *redirectBuffer) Sync() error { ++ return nil ++} ++ ++func (rb *redirectBuffer) Flush() error { ++ return nil ++} ++ ++func (rb *redirectBuffer) Write(bytes []byte) (n int, err error) { ++ return rb.w.Write(bytes) ++} ++ ++// SetOutput sets the output destination for all severities ++func SetOutput(w io.Writer) { ++ for s := fatalLog; s >= infoLog; s-- { ++ rb := &redirectBuffer{ ++ w: w, ++ } ++ logging.file[s] = rb ++ } ++} ++ ++// SetOutputBySeverity sets the output destination for specific severity ++func SetOutputBySeverity(name string, w io.Writer) { ++ sev, ok := severityByName(name) ++ if !ok { ++ panic(fmt.Sprintf("SetOutputBySeverity(%q): unrecognized severity name", name)) ++ } ++ rb := &redirectBuffer{ ++ w: w, ++ } ++ logging.file[sev] = rb ++} ++ ++// output writes the data to the log files and releases the buffer. ++func (l *loggingT) output(s severity, buf *buffer, file string, line int, alsoToStderr bool) { ++ l.mu.Lock() ++ if l.traceLocation.isSet() { ++ if l.traceLocation.match(file, line) { ++ buf.Write(stacks(false)) ++ } ++ } ++ data := buf.Bytes() ++ if l.toStderr { ++ os.Stderr.Write(data) ++ } else { ++ if alsoToStderr || l.alsoToStderr || s >= l.stderrThreshold.get() { ++ os.Stderr.Write(data) ++ } ++ if l.file[s] == nil { ++ if err := l.createFiles(s); err != nil { ++ os.Stderr.Write(data) // Make sure the message appears somewhere. ++ l.exit(err) ++ } ++ } ++ switch s { ++ case fatalLog: ++ l.file[fatalLog].Write(data) ++ fallthrough ++ case errorLog: ++ l.file[errorLog].Write(data) ++ fallthrough ++ case warningLog: ++ l.file[warningLog].Write(data) ++ fallthrough ++ case infoLog: ++ l.file[infoLog].Write(data) ++ } ++ } ++ if s == fatalLog { ++ // If we got here via Exit rather than Fatal, print no stacks. ++ if atomic.LoadUint32(&fatalNoStacks) > 0 { ++ l.mu.Unlock() ++ timeoutFlush(10 * time.Second) ++ os.Exit(1) ++ } ++ // Dump all goroutine stacks before exiting. ++ // First, make sure we see the trace for the current goroutine on standard error. ++ // If -logtostderr has been specified, the loop below will do that anyway ++ // as the first stack in the full dump. ++ if !l.toStderr { ++ os.Stderr.Write(stacks(false)) ++ } ++ // Write the stack trace for all goroutines to the files. ++ trace := stacks(true) ++ logExitFunc = func(error) {} // If we get a write error, we'll still exit below. ++ for log := fatalLog; log >= infoLog; log-- { ++ if f := l.file[log]; f != nil { // Can be nil if -logtostderr is set. ++ f.Write(trace) ++ } ++ } ++ l.mu.Unlock() ++ timeoutFlush(10 * time.Second) ++ os.Exit(255) // C++ uses -1, which is silly because it's anded with 255 anyway. ++ } ++ l.putBuffer(buf) ++ l.mu.Unlock() ++ if stats := severityStats[s]; stats != nil { ++ atomic.AddInt64(&stats.lines, 1) ++ atomic.AddInt64(&stats.bytes, int64(len(data))) ++ } ++} ++ ++// timeoutFlush calls Flush and returns when it completes or after timeout ++// elapses, whichever happens first. This is needed because the hooks invoked ++// by Flush may deadlock when glog.Fatal is called from a hook that holds ++// a lock. ++func timeoutFlush(timeout time.Duration) { ++ done := make(chan bool, 1) ++ go func() { ++ Flush() // calls logging.lockAndFlushAll() ++ done <- true ++ }() ++ select { ++ case <-done: ++ case <-time.After(timeout): ++ fmt.Fprintln(os.Stderr, "glog: Flush took longer than", timeout) ++ } ++} ++ ++// stacks is a wrapper for runtime.Stack that attempts to recover the data for all goroutines. ++func stacks(all bool) []byte { ++ // We don't know how big the traces are, so grow a few times if they don't fit. Start large, though. ++ n := 10000 ++ if all { ++ n = 100000 ++ } ++ var trace []byte ++ for i := 0; i < 5; i++ { ++ trace = make([]byte, n) ++ nbytes := runtime.Stack(trace, all) ++ if nbytes < len(trace) { ++ return trace[:nbytes] ++ } ++ n *= 2 ++ } ++ return trace ++} ++ ++// logExitFunc provides a simple mechanism to override the default behavior ++// of exiting on error. Used in testing and to guarantee we reach a required exit ++// for fatal logs. Instead, exit could be a function rather than a method but that ++// would make its use clumsier. ++var logExitFunc func(error) ++ ++// exit is called if there is trouble creating or writing log files. ++// It flushes the logs and exits the program; there's no point in hanging around. ++// l.mu is held. ++func (l *loggingT) exit(err error) { ++ fmt.Fprintf(os.Stderr, "log: exiting because of error: %s\n", err) ++ // If logExitFunc is set, we do that instead of exiting. ++ if logExitFunc != nil { ++ logExitFunc(err) ++ return ++ } ++ l.flushAll() ++ os.Exit(2) ++} ++ ++// syncBuffer joins a bufio.Writer to its underlying file, providing access to the ++// file's Sync method and providing a wrapper for the Write method that provides log ++// file rotation. There are conflicting methods, so the file cannot be embedded. ++// l.mu is held for all its methods. ++type syncBuffer struct { ++ logger *loggingT ++ *bufio.Writer ++ file *os.File ++ sev severity ++ nbytes uint64 // The number of bytes written to this file ++} ++ ++func (sb *syncBuffer) Sync() error { ++ return sb.file.Sync() ++} ++ ++func (sb *syncBuffer) Write(p []byte) (n int, err error) { ++ if sb.nbytes+uint64(len(p)) >= MaxSize { ++ if err := sb.rotateFile(time.Now(), false); err != nil { ++ sb.logger.exit(err) ++ } ++ } ++ n, err = sb.Writer.Write(p) ++ sb.nbytes += uint64(n) ++ if err != nil { ++ sb.logger.exit(err) ++ } ++ return ++} ++ ++// rotateFile closes the syncBuffer's file and starts a new one. ++// The startup argument indicates whether this is the initial startup of klog. ++// If startup is true, existing files are opened for apending instead of truncated. ++func (sb *syncBuffer) rotateFile(now time.Time, startup bool) error { ++ if sb.file != nil { ++ sb.Flush() ++ sb.file.Close() ++ } ++ var err error ++ sb.file, _, err = create(severityName[sb.sev], now, startup) ++ sb.nbytes = 0 ++ if err != nil { ++ return err ++ } ++ ++ sb.Writer = bufio.NewWriterSize(sb.file, bufferSize) ++ ++ // Write header. ++ var buf bytes.Buffer ++ fmt.Fprintf(&buf, "Log file created at: %s\n", now.Format("2006/01/02 15:04:05")) ++ fmt.Fprintf(&buf, "Running on machine: %s\n", host) ++ fmt.Fprintf(&buf, "Binary: Built with %s %s for %s/%s\n", runtime.Compiler, runtime.Version(), runtime.GOOS, runtime.GOARCH) ++ fmt.Fprintf(&buf, "Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg\n") ++ n, err := sb.file.Write(buf.Bytes()) ++ sb.nbytes += uint64(n) ++ return err ++} ++ ++// bufferSize sizes the buffer associated with each log file. It's large ++// so that log records can accumulate without the logging thread blocking ++// on disk I/O. The flushDaemon will block instead. ++const bufferSize = 256 * 1024 ++ ++// createFiles creates all the log files for severity from sev down to infoLog. ++// l.mu is held. ++func (l *loggingT) createFiles(sev severity) error { ++ now := time.Now() ++ // Files are created in decreasing severity order, so as soon as we find one ++ // has already been created, we can stop. ++ for s := sev; s >= infoLog && l.file[s] == nil; s-- { ++ sb := &syncBuffer{ ++ logger: l, ++ sev: s, ++ } ++ if err := sb.rotateFile(now, true); err != nil { ++ return err ++ } ++ l.file[s] = sb ++ } ++ return nil ++} ++ ++const flushInterval = 5 * time.Second ++ ++// flushDaemon periodically flushes the log file buffers. ++func (l *loggingT) flushDaemon() { ++ for range time.NewTicker(flushInterval).C { ++ l.lockAndFlushAll() ++ } ++} ++ ++// lockAndFlushAll is like flushAll but locks l.mu first. ++func (l *loggingT) lockAndFlushAll() { ++ l.mu.Lock() ++ l.flushAll() ++ l.mu.Unlock() ++} ++ ++// flushAll flushes all the logs and attempts to "sync" their data to disk. ++// l.mu is held. ++func (l *loggingT) flushAll() { ++ // Flush from fatal down, in case there's trouble flushing. ++ for s := fatalLog; s >= infoLog; s-- { ++ file := l.file[s] ++ if file != nil { ++ file.Flush() // ignore error ++ file.Sync() // ignore error ++ } ++ } ++} ++ ++// CopyStandardLogTo arranges for messages written to the Go "log" package's ++// default logs to also appear in the Google logs for the named and lower ++// severities. Subsequent changes to the standard log's default output location ++// or format may break this behavior. ++// ++// Valid names are "INFO", "WARNING", "ERROR", and "FATAL". If the name is not ++// recognized, CopyStandardLogTo panics. ++func CopyStandardLogTo(name string) { ++ sev, ok := severityByName(name) ++ if !ok { ++ panic(fmt.Sprintf("log.CopyStandardLogTo(%q): unrecognized severity name", name)) ++ } ++ // Set a log format that captures the user's file and line: ++ // d.go:23: message ++ stdLog.SetFlags(stdLog.Lshortfile) ++ stdLog.SetOutput(logBridge(sev)) ++} ++ ++// logBridge provides the Write method that enables CopyStandardLogTo to connect ++// Go's standard logs to the logs provided by this package. ++type logBridge severity ++ ++// Write parses the standard logging line and passes its components to the ++// logger for severity(lb). ++func (lb logBridge) Write(b []byte) (n int, err error) { ++ var ( ++ file = "???" ++ line = 1 ++ text string ++ ) ++ // Split "d.go:23: message" into "d.go", "23", and "message". ++ if parts := bytes.SplitN(b, []byte{':'}, 3); len(parts) != 3 || len(parts[0]) < 1 || len(parts[2]) < 1 { ++ text = fmt.Sprintf("bad log format: %s", b) ++ } else { ++ file = string(parts[0]) ++ text = string(parts[2][1:]) // skip leading space ++ line, err = strconv.Atoi(string(parts[1])) ++ if err != nil { ++ text = fmt.Sprintf("bad line number: %s", b) ++ line = 1 ++ } ++ } ++ // printWithFileLine with alsoToStderr=true, so standard log messages ++ // always appear on standard error. ++ logging.printWithFileLine(severity(lb), file, line, true, text) ++ return len(b), nil ++} ++ ++// setV computes and remembers the V level for a given PC ++// when vmodule is enabled. ++// File pattern matching takes the basename of the file, stripped ++// of its .go suffix, and uses filepath.Match, which is a little more ++// general than the *? matching used in C++. ++// l.mu is held. ++func (l *loggingT) setV(pc uintptr) Level { ++ fn := runtime.FuncForPC(pc) ++ file, _ := fn.FileLine(pc) ++ // The file is something like /a/b/c/d.go. We want just the d. ++ if strings.HasSuffix(file, ".go") { ++ file = file[:len(file)-3] ++ } ++ if slash := strings.LastIndex(file, "/"); slash >= 0 { ++ file = file[slash+1:] ++ } ++ for _, filter := range l.vmodule.filter { ++ if filter.match(file) { ++ l.vmap[pc] = filter.level ++ return filter.level ++ } ++ } ++ l.vmap[pc] = 0 ++ return 0 ++} ++ ++// Verbose is a boolean type that implements Infof (like Printf) etc. ++// See the documentation of V for more information. ++type Verbose bool ++ ++// V reports whether verbosity at the call site is at least the requested level. ++// The returned value is a boolean of type Verbose, which implements Info, Infoln ++// and Infof. These methods will write to the Info log if called. ++// Thus, one may write either ++// if glog.V(2) { glog.Info("log this") } ++// or ++// glog.V(2).Info("log this") ++// The second form is shorter but the first is cheaper if logging is off because it does ++// not evaluate its arguments. ++// ++// Whether an individual call to V generates a log record depends on the setting of ++// the -v and --vmodule flags; both are off by default. If the level in the call to ++// V is at least the value of -v, or of -vmodule for the source file containing the ++// call, the V call will log. ++func V(level Level) Verbose { ++ // This function tries hard to be cheap unless there's work to do. ++ // The fast path is two atomic loads and compares. ++ ++ // Here is a cheap but safe test to see if V logging is enabled globally. ++ if logging.verbosity.get() >= level { ++ return Verbose(true) ++ } ++ ++ // It's off globally but it vmodule may still be set. ++ // Here is another cheap but safe test to see if vmodule is enabled. ++ if atomic.LoadInt32(&logging.filterLength) > 0 { ++ // Now we need a proper lock to use the logging structure. The pcs field ++ // is shared so we must lock before accessing it. This is fairly expensive, ++ // but if V logging is enabled we're slow anyway. ++ logging.mu.Lock() ++ defer logging.mu.Unlock() ++ if runtime.Callers(2, logging.pcs[:]) == 0 { ++ return Verbose(false) ++ } ++ v, ok := logging.vmap[logging.pcs[0]] ++ if !ok { ++ v = logging.setV(logging.pcs[0]) ++ } ++ return Verbose(v >= level) ++ } ++ return Verbose(false) ++} ++ ++// Info is equivalent to the global Info function, guarded by the value of v. ++// See the documentation of V for usage. ++func (v Verbose) Info(args ...interface{}) { ++ if v { ++ logging.print(infoLog, args...) ++ } ++} ++ ++// Infoln is equivalent to the global Infoln function, guarded by the value of v. ++// See the documentation of V for usage. ++func (v Verbose) Infoln(args ...interface{}) { ++ if v { ++ logging.println(infoLog, args...) ++ } ++} ++ ++// Infof is equivalent to the global Infof function, guarded by the value of v. ++// See the documentation of V for usage. ++func (v Verbose) Infof(format string, args ...interface{}) { ++ if v { ++ logging.printf(infoLog, format, args...) ++ } ++} ++ ++// Info logs to the INFO log. ++// Arguments are handled in the manner of fmt.Print; a newline is appended if missing. ++func Info(args ...interface{}) { ++ logging.print(infoLog, args...) ++} ++ ++// InfoDepth acts as Info but uses depth to determine which call frame to log. ++// InfoDepth(0, "msg") is the same as Info("msg"). ++func InfoDepth(depth int, args ...interface{}) { ++ logging.printDepth(infoLog, depth, args...) ++} ++ ++// Infoln logs to the INFO log. ++// Arguments are handled in the manner of fmt.Println; a newline is appended if missing. ++func Infoln(args ...interface{}) { ++ logging.println(infoLog, args...) ++} ++ ++// Infof logs to the INFO log. ++// Arguments are handled in the manner of fmt.Printf; a newline is appended if missing. ++func Infof(format string, args ...interface{}) { ++ logging.printf(infoLog, format, args...) ++} ++ ++// Warning logs to the WARNING and INFO logs. ++// Arguments are handled in the manner of fmt.Print; a newline is appended if missing. ++func Warning(args ...interface{}) { ++ logging.print(warningLog, args...) ++} ++ ++// WarningDepth acts as Warning but uses depth to determine which call frame to log. ++// WarningDepth(0, "msg") is the same as Warning("msg"). ++func WarningDepth(depth int, args ...interface{}) { ++ logging.printDepth(warningLog, depth, args...) ++} ++ ++// Warningln logs to the WARNING and INFO logs. ++// Arguments are handled in the manner of fmt.Println; a newline is appended if missing. ++func Warningln(args ...interface{}) { ++ logging.println(warningLog, args...) ++} ++ ++// Warningf logs to the WARNING and INFO logs. ++// Arguments are handled in the manner of fmt.Printf; a newline is appended if missing. ++func Warningf(format string, args ...interface{}) { ++ logging.printf(warningLog, format, args...) ++} ++ ++// Error logs to the ERROR, WARNING, and INFO logs. ++// Arguments are handled in the manner of fmt.Print; a newline is appended if missing. ++func Error(args ...interface{}) { ++ logging.print(errorLog, args...) ++} ++ ++// ErrorDepth acts as Error but uses depth to determine which call frame to log. ++// ErrorDepth(0, "msg") is the same as Error("msg"). ++func ErrorDepth(depth int, args ...interface{}) { ++ logging.printDepth(errorLog, depth, args...) ++} ++ ++// Errorln logs to the ERROR, WARNING, and INFO logs. ++// Arguments are handled in the manner of fmt.Println; a newline is appended if missing. ++func Errorln(args ...interface{}) { ++ logging.println(errorLog, args...) ++} ++ ++// Errorf logs to the ERROR, WARNING, and INFO logs. ++// Arguments are handled in the manner of fmt.Printf; a newline is appended if missing. ++func Errorf(format string, args ...interface{}) { ++ logging.printf(errorLog, format, args...) ++} ++ ++// Fatal logs to the FATAL, ERROR, WARNING, and INFO logs, ++// including a stack trace of all running goroutines, then calls os.Exit(255). ++// Arguments are handled in the manner of fmt.Print; a newline is appended if missing. ++func Fatal(args ...interface{}) { ++ logging.print(fatalLog, args...) ++} ++ ++// FatalDepth acts as Fatal but uses depth to determine which call frame to log. ++// FatalDepth(0, "msg") is the same as Fatal("msg"). ++func FatalDepth(depth int, args ...interface{}) { ++ logging.printDepth(fatalLog, depth, args...) ++} ++ ++// Fatalln logs to the FATAL, ERROR, WARNING, and INFO logs, ++// including a stack trace of all running goroutines, then calls os.Exit(255). ++// Arguments are handled in the manner of fmt.Println; a newline is appended if missing. ++func Fatalln(args ...interface{}) { ++ logging.println(fatalLog, args...) ++} ++ ++// Fatalf logs to the FATAL, ERROR, WARNING, and INFO logs, ++// including a stack trace of all running goroutines, then calls os.Exit(255). ++// Arguments are handled in the manner of fmt.Printf; a newline is appended if missing. ++func Fatalf(format string, args ...interface{}) { ++ logging.printf(fatalLog, format, args...) ++} ++ ++// fatalNoStacks is non-zero if we are to exit without dumping goroutine stacks. ++// It allows Exit and relatives to use the Fatal logs. ++var fatalNoStacks uint32 ++ ++// Exit logs to the FATAL, ERROR, WARNING, and INFO logs, then calls os.Exit(1). ++// Arguments are handled in the manner of fmt.Print; a newline is appended if missing. ++func Exit(args ...interface{}) { ++ atomic.StoreUint32(&fatalNoStacks, 1) ++ logging.print(fatalLog, args...) ++} ++ ++// ExitDepth acts as Exit but uses depth to determine which call frame to log. ++// ExitDepth(0, "msg") is the same as Exit("msg"). ++func ExitDepth(depth int, args ...interface{}) { ++ atomic.StoreUint32(&fatalNoStacks, 1) ++ logging.printDepth(fatalLog, depth, args...) ++} ++ ++// Exitln logs to the FATAL, ERROR, WARNING, and INFO logs, then calls os.Exit(1). ++func Exitln(args ...interface{}) { ++ atomic.StoreUint32(&fatalNoStacks, 1) ++ logging.println(fatalLog, args...) ++} ++ ++// Exitf logs to the FATAL, ERROR, WARNING, and INFO logs, then calls os.Exit(1). ++// Arguments are handled in the manner of fmt.Printf; a newline is appended if missing. ++func Exitf(format string, args ...interface{}) { ++ atomic.StoreUint32(&fatalNoStacks, 1) ++ logging.printf(fatalLog, format, args...) ++} +diff --git a/vendor/k8s.io/klog/klog_file.go b/vendor/k8s.io/klog/klog_file.go +new file mode 100644 +index 0000000..1c4897f +--- /dev/null ++++ b/vendor/k8s.io/klog/klog_file.go +@@ -0,0 +1,139 @@ ++// Go support for leveled logs, analogous to https://code.google.com/p/google-glog/ ++// ++// Copyright 2013 Google Inc. All Rights Reserved. ++// ++// 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. ++ ++// File I/O for logs. ++ ++package klog ++ ++import ( ++ "errors" ++ "fmt" ++ "os" ++ "os/user" ++ "path/filepath" ++ "strings" ++ "sync" ++ "time" ++) ++ ++// MaxSize is the maximum size of a log file in bytes. ++var MaxSize uint64 = 1024 * 1024 * 1800 ++ ++// logDirs lists the candidate directories for new log files. ++var logDirs []string ++ ++func createLogDirs() { ++ if logging.logDir != "" { ++ logDirs = append(logDirs, logging.logDir) ++ } ++ logDirs = append(logDirs, os.TempDir()) ++} ++ ++var ( ++ pid = os.Getpid() ++ program = filepath.Base(os.Args[0]) ++ host = "unknownhost" ++ userName = "unknownuser" ++) ++ ++func init() { ++ h, err := os.Hostname() ++ if err == nil { ++ host = shortHostname(h) ++ } ++ ++ current, err := user.Current() ++ if err == nil { ++ userName = current.Username ++ } ++ ++ // Sanitize userName since it may contain filepath separators on Windows. ++ userName = strings.Replace(userName, `\`, "_", -1) ++} ++ ++// shortHostname returns its argument, truncating at the first period. ++// For instance, given "www.google.com" it returns "www". ++func shortHostname(hostname string) string { ++ if i := strings.Index(hostname, "."); i >= 0 { ++ return hostname[:i] ++ } ++ return hostname ++} ++ ++// logName returns a new log file name containing tag, with start time t, and ++// the name for the symlink for tag. ++func logName(tag string, t time.Time) (name, link string) { ++ name = fmt.Sprintf("%s.%s.%s.log.%s.%04d%02d%02d-%02d%02d%02d.%d", ++ program, ++ host, ++ userName, ++ tag, ++ t.Year(), ++ t.Month(), ++ t.Day(), ++ t.Hour(), ++ t.Minute(), ++ t.Second(), ++ pid) ++ return name, program + "." + tag ++} ++ ++var onceLogDirs sync.Once ++ ++// create creates a new log file and returns the file and its filename, which ++// contains tag ("INFO", "FATAL", etc.) and t. If the file is created ++// successfully, create also attempts to update the symlink for that tag, ignoring ++// errors. ++// The startup argument indicates whether this is the initial startup of klog. ++// If startup is true, existing files are opened for apending instead of truncated. ++func create(tag string, t time.Time, startup bool) (f *os.File, filename string, err error) { ++ if logging.logFile != "" { ++ f, err := openOrCreate(logging.logFile, startup) ++ if err == nil { ++ return f, logging.logFile, nil ++ } ++ return nil, "", fmt.Errorf("log: unable to create log: %v", err) ++ } ++ onceLogDirs.Do(createLogDirs) ++ if len(logDirs) == 0 { ++ return nil, "", errors.New("log: no log dirs") ++ } ++ name, link := logName(tag, t) ++ var lastErr error ++ for _, dir := range logDirs { ++ fname := filepath.Join(dir, name) ++ f, err := openOrCreate(fname, startup) ++ if err == nil { ++ symlink := filepath.Join(dir, link) ++ os.Remove(symlink) // ignore err ++ os.Symlink(name, symlink) // ignore err ++ return f, fname, nil ++ } ++ lastErr = err ++ } ++ return nil, "", fmt.Errorf("log: cannot create log: %v", lastErr) ++} ++ ++// The startup argument indicates whether this is the initial startup of klog. ++// If startup is true, existing files are opened for appending instead of truncated. ++func openOrCreate(name string, startup bool) (*os.File, error) { ++ if startup { ++ f, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) ++ return f, err ++ } ++ f, err := os.Create(name) ++ return f, err ++} diff --git a/debian/patches/series b/debian/patches/series new file mode 100644 index 0000000..231ad34 --- /dev/null +++ b/debian/patches/series @@ -0,0 +1,3 @@ +ftbfs-arm.patch +klog.patch +ignore-arch-tests.patch diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..9385ef3 --- /dev/null +++ b/debian/rules @@ -0,0 +1,13 @@ +#!/usr/bin/make -f + +# install all files for dockerfile/parser to pickup the various testfiles +# Ideally, upstream would move all test files out to 'testdata/', which seems +# to be a common best-practice in many other golang projects, and +# detected automatically by the golang debhelper +export DH_GOLANG_INSTALL_EXTRA := dockerfile/parser + +# avoid installing test utility +export DH_GOLANG_EXCLUDES := dumper + +%: + dh $@ --buildsystem=golang --with=golang diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 0000000..163aaf8 --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/debian/source/lintian-overrides b/debian/source/lintian-overrides new file mode 100644 index 0000000..53a1f62 --- /dev/null +++ b/debian/source/lintian-overrides @@ -0,0 +1,2 @@ +# contains testdata that is not really an .a archive +golang-github-openshift-imagebuilder source: unpack-message-for-orig diff --git a/debian/upstream/metadata b/debian/upstream/metadata new file mode 100644 index 0000000..f69b88a --- /dev/null +++ b/debian/upstream/metadata @@ -0,0 +1,5 @@ +--- +Bug-Database: https://github.com/openshift/imagebuilder/issues +Bug-Submit: https://github.com/openshift/imagebuilder/issues/new +Repository: https://github.com/openshift/imagebuilder.git +Repository-Browse: https://github.com/openshift/imagebuilder diff --git a/debian/watch b/debian/watch new file mode 100644 index 0000000..ecb9d10 --- /dev/null +++ b/debian/watch @@ -0,0 +1,10 @@ +version=4 +opts="\ +pgpmode=none,\ +repacksuffix=+ds1,\ +repack,compression=xz,\ +dirversionmangle=s/-rc/~rc/,\ +uversionmangle=s/-rc/~rc/,\ +dversionmangle=s{[+~]ds\d*}{},\ +" https://github.com/openshift/imagebuilder/tags \ + .*/v?@ANY_VERSION@@ARCHIVE_EXT@ |