Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improvements #4

Merged
merged 3 commits into from
Aug 12, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ LICENSE
NOTICE
docs
cloudconfig
*.tar
*.tar.gz
29 changes: 0 additions & 29 deletions Dockerfile

This file was deleted.

14 changes: 3 additions & 11 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,13 @@ import (
"github.com/tylerb/graceful"

"github.com/coreos/clair/database"
"github.com/coreos/clair/pkg/config"
"github.com/coreos/clair/pkg/stopper"
)

const timeoutResponse = `{"Error":{"Message":"Clair failed to respond within the configured timeout window.","Type":"Timeout"}}`

// Config is the configuration for the API service.
type Config struct {
Port int
HealthPort int
Timeout time.Duration
PaginationKey string
CertFile, KeyFile, CAFile string
}

func Run(cfg *Config, store database.Datastore, st *stopper.Stopper) {
func Run(cfg *config.APIConfig, store database.Datastore, st *stopper.Stopper) {
defer st.End()

// Do not run the API service if there is no config.
Expand Down Expand Up @@ -74,7 +66,7 @@ func Run(cfg *Config, store database.Datastore, st *stopper.Stopper) {
log.Info("main API stopped")
}

func RunHealth(cfg *Config, store database.Datastore, st *stopper.Stopper) {
func RunHealth(cfg *config.APIConfig, store database.Datastore, st *stopper.Stopper) {
defer st.End()

// Do not run the API service if there is no config.
Expand Down
3 changes: 2 additions & 1 deletion api/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (

"github.com/coreos/clair/api/v1"
"github.com/coreos/clair/database"
"github.com/coreos/clair/pkg/config"
)

// router is an HTTP router that forwards requests to the appropriate sub-router
Expand All @@ -32,7 +33,7 @@ type router map[string]*httprouter.Router
// Let's hope we never have more than 99 API versions.
const apiVersionLength = len("v99")

func newAPIHandler(cfg *Config, store database.Datastore) http.Handler {
func newAPIHandler(cfg *config.APIConfig, store database.Datastore) http.Handler {
router := make(router)
router["/v1"] = v1.NewRouter(store, cfg.PaginationKey)
return router
Expand Down
20 changes: 20 additions & 0 deletions build/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
FROM golang:1.10-alpine as base
ADD . /go/src/github.com/coreos/clair/
WORKDIR /go/src/github.com/coreos/clair/
RUN apk add --no-cache git rpm xz
RUN export CLAIR_VERSION=$(git describe --always --tags --dirty) \
&& go install -ldflags "-X github.com/coreos/clair/pkg/version.Version=$CLAIR_VERSION" -v github.com/coreos/clair/cmd/clair

FROM alpine:3.8
LABEL maintainer="[email protected]"
RUN apk add --no-cache git rpm xz
COPY --from=base /go/bin/clair /clair
COPY build/dumb-init /dumb-init
VOLUME /config
EXPOSE 6060 6061
RUN chmod +x /clair \
&& chmod +x /dumb-init
HEALTHCHECK --interval=30s --timeout=10s --retries=3 CMD wget -qO- 127.0.0.1:6061/health || exit 1
ENTRYPOINT ["/dumb-init", "--"]
CMD ["/clair", "-config", "/config/config.yaml"]

Binary file added build/dumb-init
Binary file not shown.
15 changes: 10 additions & 5 deletions cmd/clair/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/coreos/clair/api"
"github.com/coreos/clair/database"
"github.com/coreos/clair/ext/imagefmt"
appconfig "github.com/coreos/clair/pkg/config"
"github.com/coreos/clair/pkg/formatter"
"github.com/coreos/clair/pkg/stopper"

Expand Down Expand Up @@ -87,7 +88,7 @@ func stopCPUProfiling(f *os.File) {
}

// Boot starts Clair instance with the provided config.
func Boot(config *Config) {
func Boot(config *appconfig.Config) {
rand.Seed(time.Now().UnixNano())
st := stopper.NewStopper()

Expand All @@ -110,8 +111,12 @@ func Boot(config *Config) {

// Start updater
st.Begin()
// go clair.RunUpdater(config.Updater, db, st)
go updater.ScheduleUpdater(db)
if !config.Updater.Disabled {
log.Info("Start regular updater")
go updater.ScheduleUpdater(db, config.Updater.Cron)
} else {
log.Info("Updater is disabled")
}

// Wait for interruption and shutdown gracefully.
waitForSignals(syscall.SIGINT, syscall.SIGTERM)
Expand All @@ -137,13 +142,13 @@ func main() {
}

// Load configuration
config, err := LoadConfig(*flagConfigPath)
config, err := appconfig.LoadConfig(*flagConfigPath)
if err != nil {
log.WithError(err).Fatal("failed to load configuration")
}
appconfig.AppConfig = config

// Initialize logging system

logLevel, err := log.ParseLevel(strings.ToUpper(*flagLogLevel))
log.SetLevel(logLevel)
log.SetOutput(os.Stdout)
Expand Down
5 changes: 3 additions & 2 deletions config.example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,9 @@ clair:

updater:
# Frequency the database will be updated with vulnerabilities from the default data sources
# The value 0 disables the updater entirely.
interval: 2h
cron: "@midnight"
# Whether disable the regular updater
disabled: false

notifier:
# Number of attempts before the notification is marked as failed to be sent
Expand Down
51 changes: 28 additions & 23 deletions cmd/clair/config.go → pkg/config/config.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,4 @@
// Copyright 2017 clair 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
//
// 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 main
package config

import (
"errors"
Expand All @@ -22,8 +8,6 @@ import (

"gopkg.in/yaml.v2"

"github.com/coreos/clair"
"github.com/coreos/clair/api"
"github.com/coreos/clair/database"
"github.com/coreos/clair/ext/notification"
"github.com/fernet/fernet-go"
Expand All @@ -39,24 +23,45 @@ type File struct {
Clair Config `yaml:"clair"`
}

// UpdaterConfig configures the regularly updater by cron
type UpdaterConfig struct {
// Cron defines when to update, refer to https://godoc.org/github.com/robfig/cron
Cron string
// Disabled indicates whether the regular updater is disabled
Disabled bool
}

// Config is the configuration for the API service.
type APIConfig struct {
Port int
HealthPort int
Timeout time.Duration
PaginationKey string
CertFile, KeyFile, CAFile string
}

// Config is the global configuration for an instance of Clair.
type Config struct {
Database database.RegistrableComponentConfig
Updater *clair.UpdaterConfig
Updater *UpdaterConfig
Notifier *notification.Config
API *api.Config
API *APIConfig
}

// AppConfig is config loaded
var AppConfig *Config

// DefaultConfig is a configuration that can be used as a fallback value.
func DefaultConfig() Config {
return Config{
Database: database.RegistrableComponentConfig{
Type: "pgsql",
},
Updater: &clair.UpdaterConfig{
Interval: 1 * time.Hour,
Updater: &UpdaterConfig{
Cron: "@midnight",
Disabled: false,
},
API: &api.Config{
API: &APIConfig{
Port: 6060,
HealthPort: 6061,
Timeout: 900 * time.Second,
Expand Down Expand Up @@ -105,7 +110,7 @@ func LoadConfig(path string) (config *Config, err error) {
} else {
_, err = fernet.DecodeKey(config.API.PaginationKey)
if err != nil {
err = errors.New("Invalid Pagination key; must be 32-bit URL-safe base64")
err = errors.New("invalid Pagination key; must be 32-bit URL-safe base64")
return
}
}
Expand Down
16 changes: 14 additions & 2 deletions pkg/updater/cron.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package updater
import (
"github.com/coreos/clair"
"github.com/coreos/clair/database"
"github.com/coreos/clair/pkg/config"

"github.com/robfig/cron"
log "github.com/sirupsen/logrus"
Expand All @@ -12,12 +13,16 @@ const UpdaterScheduleSetting = "updater-schedule"

var c *cron.Cron

func ScheduleUpdater(db database.Datastore) {
func ScheduleUpdater(db database.Datastore, defaultCron string) {
updaterSchedule, err := db.GetSetting(UpdaterScheduleSetting)
if err != nil {
log.Fatalf("Get setting '%s' error: %v", UpdaterScheduleSetting, err)
}

if len(updaterSchedule) == 0 {
updaterSchedule = defaultCron
}

_, err = cron.Parse(updaterSchedule)
if err != nil {
log.Fatalf("Invalid cron spec '%s': %v", updaterSchedule, err)
Expand Down Expand Up @@ -48,7 +53,14 @@ func UpdateSchedule(db database.Datastore, schedule string) error {
return err
}

c.Stop()
if config.AppConfig.Updater.Disabled {
log.Info("Updater not scheduled as disabled")
return nil
}

if c != nil {
c.Stop()
}
c = cron.New()
c.AddFunc(schedule, func() {
log.Info("Start vulnerabilities database update by cron schedule.")
Expand Down
Loading