Skip to content

Commit

Permalink
Merge pull request #193 from listx/fix-auditor
Browse files Browse the repository at this point in the history
Fix auditor
  • Loading branch information
k8s-ci-robot authored Mar 10, 2020
2 parents 9ccd06a + 0e4c23f commit 022877c
Show file tree
Hide file tree
Showing 8 changed files with 228 additions and 58 deletions.
7 changes: 5 additions & 2 deletions lib/audit/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")

go_library(
name = "go_default_library",
srcs = ["auditor.go"],
srcs = [
"auditor.go",
"types.go",
],
importpath = "sigs.k8s.io/k8s-container-image-promoter/lib/audit",
visibility = ["//visibility:public"],
deps = [
"//lib/dockerregistry:go_default_library",
"//lib/logclient:go_default_library",
"@com_google_cloud_go//errorreporting:go_default_library",
"@com_google_cloud_go_logging//:go_default_library",
"@in_gopkg_src_d_go_git_v4//:go_default_library",
"@in_gopkg_src_d_go_git_v4//plumbing:go_default_library",
"@io_k8s_klog//:go_default_library",
Expand Down
62 changes: 7 additions & 55 deletions lib/audit/auditor.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,42 +29,11 @@ import (
"strings"

"cloud.google.com/go/errorreporting"
"cloud.google.com/go/logging"
git "gopkg.in/src-d/go-git.v4"
"gopkg.in/src-d/go-git.v4/plumbing"
"k8s.io/klog"
reg "sigs.k8s.io/k8s-container-image-promoter/lib/dockerregistry"
)

// ServerContext holds all of the initialization data for the server to start
// up.
type ServerContext struct {
ID string
RepoURL *url.URL
RepoBranch string
ThinManifestDirPath string
ErrorReportingClient *errorreporting.Client
LogClient *logging.Client
}

// PubSubMessageInner is the inner struct that holds the actual Pub/Sub
// information.
type PubSubMessageInner struct {
Data []byte `json:"data,omitempty"`
ID string `json:"id"`
}

// PubSubMessage is the payload of a Pub/Sub event.
type PubSubMessage struct {
Message PubSubMessageInner `json:"message"`
Subscription string `json:"subscription"`
}

const (
cloneDepth = 1
// LogName is the auditing log name to use. This is the name that comes up
// for "gcloud logging logs list".
LogName = "cip-audit-log"
"sigs.k8s.io/k8s-container-image-promoter/lib/logclient"
)

func initServerContext(
Expand All @@ -77,37 +46,20 @@ func initServerContext(
}

erc := initErrorReportingClient(gcpProjectID)
logClient := initLogClient(gcpProjectID)
loggingFacility := logclient.NewGcpLoggingFacility(gcpProjectID, LogName)

serverContext := ServerContext{
ID: uuid,
RepoURL: repoURL,
RepoBranch: branch,
ThinManifestDirPath: path,
ErrorReportingClient: erc,
LogClient: logClient,
LoggingFacility: loggingFacility,
}

return &serverContext, nil
}

// initLogClient creates a logging client that performs better logging than the
// default behavior on GCP Stackdriver. For instance, logs sent with this client
// are not split up over newlines, and also the severity levels are actually
// understood by Stackdriver.
func initLogClient(projectID string) *logging.Client {

ctx := context.Background()

// Creates a client.
client, err := logging.NewClient(ctx, projectID)
if err != nil {
klog.Fatalf("Failed to create client: %v", err)
}

return client
}

func initErrorReportingClient(projectID string) *errorreporting.Client {

ctx := context.Background()
Expand Down Expand Up @@ -137,7 +89,7 @@ func Auditor(gcpProjectID, repoURL, branch, path, uuid string) {
klog.Infoln(serverContext)

// nolint[errcheck]
defer serverContext.LogClient.Close()
defer serverContext.LoggingFacility.Close()
// nolint[errcheck]
defer serverContext.ErrorReportingClient.Close()

Expand Down Expand Up @@ -277,9 +229,9 @@ func ParsePubSubMessage(r *http.Request) (*reg.GCRPubSubPayload, error) {
// other.
// nolint[funlen]
func (s *ServerContext) Audit(w http.ResponseWriter, r *http.Request) {
logInfo := s.LogClient.Logger(LogName).StandardLogger(logging.Info)
logError := s.LogClient.Logger(LogName).StandardLogger(logging.Error)
logAlert := s.LogClient.Logger(LogName).StandardLogger(logging.Alert)
logInfo := s.LoggingFacility.LogInfo
logError := s.LoggingFacility.LogError
logAlert := s.LoggingFacility.LogAlert

defer func() {
if msg := recover(); msg != nil {
Expand Down
55 changes: 55 additions & 0 deletions lib/audit/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
Copyright 2020 The Kubernetes Authors.
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
https://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 audit

import (
"net/url"

"cloud.google.com/go/errorreporting"
"sigs.k8s.io/k8s-container-image-promoter/lib/logclient"
)

// ServerContext holds all of the initialization data for the server to start
// up.
type ServerContext struct {
ID string
RepoURL *url.URL
RepoBranch string
ThinManifestDirPath string
ErrorReportingClient *errorreporting.Client
LoggingFacility *logclient.LoggingFacility
}

// PubSubMessageInner is the inner struct that holds the actual Pub/Sub
// information.
type PubSubMessageInner struct {
Data []byte `json:"data,omitempty"`
ID string `json:"id"`
}

// PubSubMessage is the payload of a Pub/Sub event.
type PubSubMessage struct {
Message PubSubMessageInner `json:"message"`
Subscription string `json:"subscription"`
}

const (
cloneDepth = 1
// LogName is the auditing log name to use. This is the name that comes up
// for "gcloud logging logs list".
LogName = "cip-audit-log"
)
2 changes: 1 addition & 1 deletion lib/dockerregistry/inventory.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ func ValidateThinManifestDirectoryStructure(
return err
}

fmt.Printf("*looking at %q\n", dir)
klog.Infof("*looking at %q", dir)
for _, file := range files {
p, err := os.Stat(filepath.Join(manifestDir, file.Name()))
if err != nil {
Expand Down
16 changes: 16 additions & 0 deletions lib/logclient/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")

go_library(
name = "go_default_library",
srcs = [
"fake.go",
"gcp.go",
"types.go",
],
importpath = "sigs.k8s.io/k8s-container-image-promoter/lib/logclient",
visibility = ["//visibility:public"],
deps = [
"@com_google_cloud_go_logging//:go_default_library",
"@io_k8s_klog//:go_default_library",
],
)
40 changes: 40 additions & 0 deletions lib/logclient/fake.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
Copyright 2020 The Kubernetes Authors.
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
https://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 logclient

import (
"log"
"os"
)

// FakeLogClient is a fake log client. Its sole purpose is to implement a NOP
// "Close()" method, for tests.
type FakeLogClient struct{}

// Close is a NOP (there is nothing to close).
func (fakeLogClient *FakeLogClient) Close() error { return nil }

// NewFakeLoggingFacility returns a new LoggingFacility, but whose resources are
// all local (stdout), with a FakeLogClient.
func NewFakeLoggingFacility() *LoggingFacility {

logInfo := log.New(os.Stdout, "FAKE-INFO", log.LstdFlags)
logError := log.New(os.Stdout, "FAKE-ERROR", log.LstdFlags)
logAlert := log.New(os.Stdout, "FAKE-ALERT", log.LstdFlags)

return New(logInfo, logError, logAlert, &FakeLogClient{})
}
54 changes: 54 additions & 0 deletions lib/logclient/gcp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
Copyright 2020 The Kubernetes Authors.
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
https://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 logclient

import (
"context"

"cloud.google.com/go/logging"
"k8s.io/klog"
)

// NewGcpLoggingFacility returns a new LoggingFacility that logs to GCP
// resources. As such, it requires the GCP projectID as well as the logName to
// log to.
func NewGcpLoggingFacility(projectID, logName string) *LoggingFacility {
gcpLogClient := initGcpLogClient(projectID)

logInfo := gcpLogClient.Logger(logName).StandardLogger(logging.Info)
logError := gcpLogClient.Logger(logName).StandardLogger(logging.Error)
logAlert := gcpLogClient.Logger(logName).StandardLogger(logging.Alert)

return New(logInfo, logError, logAlert, gcpLogClient)
}

// initGcpLogClient creates a logging client that performs better logging than
// the default behavior on GCP Stackdriver. For instance, logs sent with this
// client are not split up over newlines, and also the severity levels are
// actually understood by Stackdriver.
func initGcpLogClient(projectID string) *logging.Client {

ctx := context.Background()

// Creates a client.
client, err := logging.NewClient(ctx, projectID)
if err != nil {
klog.Fatalf("Failed to create client: %v", err)
}

return client
}
50 changes: 50 additions & 0 deletions lib/logclient/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
Copyright 2020 The Kubernetes Authors.
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
https://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 logclient

import (
"io"
"log"
)

// LoggingFacility bundles 3 loggers together.
type LoggingFacility struct {
LogInfo *log.Logger
LogError *log.Logger
LogAlert *log.Logger

logClient io.Closer
}

// New returns a new LoggingFacility, based on the given loggers.
func New(
logInfo, logError, logAlert *log.Logger,
logClient io.Closer,
) *LoggingFacility {
return &LoggingFacility{
LogInfo: logInfo,
LogError: logError,
LogAlert: logAlert,
logClient: logClient,
}
}

// Close implements the "Close" method for the LoggingFacility. This just calls
// Close() on the "logClient".
func (loggingFacility *LoggingFacility) Close() error {
return loggingFacility.logClient.Close()
}

0 comments on commit 022877c

Please sign in to comment.