diff --git a/cmd/ignite-spawn/ignite-spawn.go b/cmd/ignite-spawn/ignite-spawn.go index 58bdce409..8007f7823 100644 --- a/cmd/ignite-spawn/ignite-spawn.go +++ b/cmd/ignite-spawn/ignite-spawn.go @@ -14,12 +14,13 @@ import ( "github.com/weaveworks/ignite/pkg/container/prometheus" "github.com/weaveworks/ignite/pkg/dmlegacy" "github.com/weaveworks/ignite/pkg/providers" + "github.com/weaveworks/ignite/pkg/providers/spawn" patchutil "github.com/weaveworks/ignite/pkg/util/patch" ) func main() { // Populate the providers - cmdutil.CheckErr(providers.Populate(providers.Providers)) + cmdutil.CheckErr(providers.Populate(spawn.Providers)) RunIgniteSpawn() } diff --git a/cmd/ignite/cmd/daemon.go b/cmd/ignite/cmd/daemon.go index e723450a8..ad3235279 100644 --- a/cmd/ignite/cmd/daemon.go +++ b/cmd/ignite/cmd/daemon.go @@ -10,6 +10,7 @@ import ( "github.com/spf13/cobra" "github.com/weaveworks/ignite/cmd/ignite/cmd/cmdutil" "github.com/weaveworks/ignite/pkg/providers" + "github.com/weaveworks/ignite/pkg/providers/ignite" ) func NewCmdDaemon(out io.Writer) *cobra.Command { @@ -19,7 +20,7 @@ func NewCmdDaemon(out io.Writer) *cobra.Command { Hidden: true, Run: func(cmd *cobra.Command, args []string) { // Initialize the daemon providers (e.g. ManifestStorage) - cmdutil.CheckErr(providers.Populate(providers.DaemonProviders)) + cmdutil.CheckErr(providers.Populate(ignite.DaemonProviders)) // Wait for Ctrl + C var endWaiter sync.WaitGroup @@ -35,11 +36,9 @@ func NewCmdDaemon(out io.Writer) *cobra.Command { endWaiter.Wait() - // Close the SyncStorage's watcher threads - if providers.SyncStorage != nil { - fmt.Println("Closing...") - providers.SyncStorage.Close() - } + // Close the Storage's watcher threads + fmt.Println("Closing...") + providers.Storage.Close() }, } diff --git a/cmd/ignite/ignite.go b/cmd/ignite/ignite.go index 16f51eb9e..b3f1f95bc 100644 --- a/cmd/ignite/ignite.go +++ b/cmd/ignite/ignite.go @@ -6,6 +6,7 @@ import ( "github.com/weaveworks/ignite/cmd/ignite/cmd" "github.com/weaveworks/ignite/cmd/ignite/cmd/cmdutil" "github.com/weaveworks/ignite/pkg/providers" + "github.com/weaveworks/ignite/pkg/providers/ignite" ) func main() { @@ -17,7 +18,7 @@ func main() { // Run runs the main cobra command of this application func Run() error { // Populate the providers - cmdutil.CheckErr(providers.Populate(providers.Providers)) + cmdutil.CheckErr(providers.Populate(ignite.Providers)) c := cmd.NewIgniteCommand(os.Stdin, os.Stdout, os.Stderr) return c.Execute() diff --git a/hack/cobra.go b/hack/cobra.go index d42e1df58..98ed99199 100644 --- a/hack/cobra.go +++ b/hack/cobra.go @@ -8,10 +8,11 @@ import ( "github.com/spf13/cobra/doc" "github.com/weaveworks/ignite/cmd/ignite/cmd" "github.com/weaveworks/ignite/pkg/providers" + "github.com/weaveworks/ignite/pkg/providers/ignite" ) func main() { - if err := providers.Populate(providers.Providers); err != nil { + if err := providers.Populate(ignite.Providers); err != nil { log.Fatal(err) } ignite := cmd.NewIgniteCommand(os.Stdin, os.Stdout, os.Stderr) diff --git a/pkg/network/cni/cni.go b/pkg/network/cni/cni.go index c3f0b7b0b..f906bdeb7 100644 --- a/pkg/network/cni/cni.go +++ b/pkg/network/cni/cni.go @@ -10,6 +10,7 @@ import ( "github.com/containernetworking/cni/libcni" cnitypes "github.com/containernetworking/cni/pkg/types" log "github.com/sirupsen/logrus" + "github.com/weaveworks/ignite/pkg/network" "github.com/weaveworks/ignite/pkg/runtime" ) @@ -33,7 +34,7 @@ type cniNetwork struct { CNIConfig libcni.CNI } -func GetCNINetworkPlugin(runtime runtime.Interface) (NetworkPlugin, error) { +func GetCNINetworkPlugin(runtime runtime.Interface) (network.Plugin, error) { binDirs := []string{CNIBinDir} plugin := &cniNetworkPlugin{ runtime: runtime, diff --git a/pkg/network/cni/types.go b/pkg/network/cni/types.go index a52011619..1ead5e9d4 100644 --- a/pkg/network/cni/types.go +++ b/pkg/network/cni/types.go @@ -19,18 +19,3 @@ const ( }] }` ) - -// NetworkPlugin describes a network plugin for docker -type NetworkPlugin interface { - // Name returns the network plugin's name. - Name() string - - // SetupContainerNetwork sets up the networking for a Docker container using CNI - SetupContainerNetwork(containerID string) error - - // RemoveContainerNetwork is the method called before a container using the CNI network can be deleted - RemoveContainerNetwork(containerID string) error - - // Status returns error if the network plugin is in error state - Status() error -} diff --git a/pkg/network/types.go b/pkg/network/types.go new file mode 100644 index 000000000..98fc80281 --- /dev/null +++ b/pkg/network/types.go @@ -0,0 +1,16 @@ +package network + +// Plugin describes a generic network plugin +type Plugin interface { + // Name returns the network plugin's name. + Name() string + + // SetupContainerNetwork sets up the networking for a container + SetupContainerNetwork(containerID string) error + + // RemoveContainerNetwork is the method called before a container using the network plugin can be deleted + RemoveContainerNetwork(containerID string) error + + // Status returns error if the network plugin is in error state + Status() error +} diff --git a/pkg/providers/client.go b/pkg/providers/client.go deleted file mode 100644 index eec9474c0..000000000 --- a/pkg/providers/client.go +++ /dev/null @@ -1,11 +0,0 @@ -package providers - -import "github.com/weaveworks/ignite/pkg/client" - -// Client is the default client that can be easily used -var Client *client.Client - -func SetClient() error { - Client = client.NewClient(Storage) - return nil -} diff --git a/pkg/providers/client/client.go b/pkg/providers/client/client.go new file mode 100644 index 000000000..0e7373d9d --- /dev/null +++ b/pkg/providers/client/client.go @@ -0,0 +1,13 @@ +package client + +import ( + log "github.com/sirupsen/logrus" + "github.com/weaveworks/ignite/pkg/client" + "github.com/weaveworks/ignite/pkg/providers" +) + +func SetClient() (err error) { + log.Trace("Initializing the Client provider...") + providers.Client = client.NewClient(providers.Storage) + return +} diff --git a/pkg/providers/cni/cni.go b/pkg/providers/cni/cni.go new file mode 100644 index 000000000..bd73d4351 --- /dev/null +++ b/pkg/providers/cni/cni.go @@ -0,0 +1,13 @@ +package cni + +import ( + log "github.com/sirupsen/logrus" + "github.com/weaveworks/ignite/pkg/network/cni" + "github.com/weaveworks/ignite/pkg/providers" +) + +func SetCNINetworkPlugin() (err error) { + log.Trace("Initializing the CNI provider...") + providers.NetworkPlugin, err = cni.GetCNINetworkPlugin(providers.Runtime) + return +} diff --git a/pkg/providers/docker/runtime.go b/pkg/providers/docker/runtime.go new file mode 100644 index 000000000..a73dd3e54 --- /dev/null +++ b/pkg/providers/docker/runtime.go @@ -0,0 +1,13 @@ +package docker + +import ( + log "github.com/sirupsen/logrus" + "github.com/weaveworks/ignite/pkg/providers" + "github.com/weaveworks/ignite/pkg/runtime/docker" +) + +func SetDockerRuntime() (err error) { + log.Trace("Initializing the Docker provider...") + providers.Runtime, err = docker.GetDockerClient() + return +} diff --git a/pkg/providers/ignite/providers.go b/pkg/providers/ignite/providers.go new file mode 100644 index 000000000..979699285 --- /dev/null +++ b/pkg/providers/ignite/providers.go @@ -0,0 +1,25 @@ +package ignite + +import ( + "github.com/weaveworks/ignite/pkg/providers" + clientprovider "github.com/weaveworks/ignite/pkg/providers/client" + cniprovider "github.com/weaveworks/ignite/pkg/providers/cni" + dockerprovider "github.com/weaveworks/ignite/pkg/providers/docker" + storageprovider "github.com/weaveworks/ignite/pkg/providers/storage" +) + +// NOTE: Provider initialization is order-dependent! +// E.g. the network plugin depends on the runtime. +var Providers = []providers.ProviderInitFunc{ + dockerprovider.SetDockerRuntime, // Use the Docker runtime + cniprovider.SetCNINetworkPlugin, // Use the CNI Network plugin + storageprovider.SetGenericStorage, // Use a generic storage implementation backed by a cache + clientprovider.SetClient, // Set the globally available client +} + +// `ignite daemon` overwrites/re-initializes the Storage and Client providers +// TODO: Break this into its own binary +var DaemonProviders = []providers.ProviderInitFunc{ + storageprovider.SetManifestStorage, // Use the ManifestStorage implementation + clientprovider.SetClient, // Set the globally available client +} diff --git a/pkg/providers/network.go b/pkg/providers/network.go deleted file mode 100644 index e822c0f18..000000000 --- a/pkg/providers/network.go +++ /dev/null @@ -1,13 +0,0 @@ -package providers - -import ( - "github.com/weaveworks/ignite/pkg/network/cni" -) - -// NetworkPlugin provides the default network plugin implementation -var NetworkPlugin cni.NetworkPlugin - -func SetCNINetworkPlugin() (err error) { - NetworkPlugin, err = cni.GetCNINetworkPlugin(Runtime) - return -} diff --git a/pkg/providers/providers.go b/pkg/providers/providers.go index 5074416ae..7ebd283f0 100644 --- a/pkg/providers/providers.go +++ b/pkg/providers/providers.go @@ -1,24 +1,32 @@ package providers -// NOTE: Provider initialization is order-dependent! -// E.g. the network plugin depends on the runtime. -var Providers = []func() error{ - SetDockerRuntime, // Use the Docker runtime - SetCNINetworkPlugin, // Use the CNI Network plugin - SetCachedStorage, // Use a generic storage implementation backed by a cache - SetClient, // Set the globally available client -} +import ( + log "github.com/sirupsen/logrus" + "github.com/weaveworks/ignite/pkg/client" + "github.com/weaveworks/ignite/pkg/network" + "github.com/weaveworks/ignite/pkg/runtime" + "github.com/weaveworks/ignite/pkg/storage" +) -// `ignite daemon` overwrites/re-initializes the Storage and Client providers -var DaemonProviders = []func() error{ - SetManifestStorage, // Use the ManifestStorage implementation - SetClient, // Set the globally available client -} +// NetworkPlugin provides the default network plugin implementation +var NetworkPlugin network.Plugin -// Populate initializes all providers -func Populate(providers []func() error) error { +// Runtime provides the default container runtime +var Runtime runtime.Interface + +// Client is the default client that can be easily used +var Client *client.Client - for _, init := range providers { +// Storage is the default storage implementation +var Storage storage.Storage + +type ProviderInitFunc func() error + +// Populate initializes all providers +func Populate(providers []ProviderInitFunc) error { + log.Trace("Populating providers...") + for i, init := range providers { + log.Tracef("Provider %d...", i) if err := init(); err != nil { return err } diff --git a/pkg/providers/runtime.go b/pkg/providers/runtime.go deleted file mode 100644 index 4cb46f13c..000000000 --- a/pkg/providers/runtime.go +++ /dev/null @@ -1,14 +0,0 @@ -package providers - -import ( - "github.com/weaveworks/ignite/pkg/runtime" - "github.com/weaveworks/ignite/pkg/runtime/docker" -) - -// Runtime provides the default runtime -var Runtime runtime.Interface - -func SetDockerRuntime() (err error) { - Runtime, err = docker.GetDockerClient() - return -} diff --git a/pkg/providers/spawn/provider.go b/pkg/providers/spawn/provider.go new file mode 100644 index 000000000..0ab67d5b7 --- /dev/null +++ b/pkg/providers/spawn/provider.go @@ -0,0 +1,14 @@ +package spawn + +import ( + "github.com/weaveworks/ignite/pkg/providers" + clientprovider "github.com/weaveworks/ignite/pkg/providers/client" + storageprovider "github.com/weaveworks/ignite/pkg/providers/storage" +) + +// NOTE: Provider initialization is order-dependent! +// E.g. the network plugin depends on the runtime. +var Providers = []providers.ProviderInitFunc{ + storageprovider.SetGenericStorage, // Use a generic storage implementation backed by a cache + clientprovider.SetClient, // Set the globally available client +} diff --git a/pkg/providers/storage.go b/pkg/providers/storage.go deleted file mode 100644 index c0121c2c7..000000000 --- a/pkg/providers/storage.go +++ /dev/null @@ -1,41 +0,0 @@ -package providers - -import ( - "github.com/weaveworks/ignite/pkg/apis/ignite/scheme" - "github.com/weaveworks/ignite/pkg/constants" - "github.com/weaveworks/ignite/pkg/storage" - "github.com/weaveworks/ignite/pkg/storage/cache" - "github.com/weaveworks/ignite/pkg/storage/manifest/raw" - "github.com/weaveworks/ignite/pkg/storage/sync" - "github.com/weaveworks/ignite/pkg/storage/watch" -) - -// Storage is the default storage implementation -var Storage storage.Storage - -// SyncStorage is used to close the ManifestStorage -var SyncStorage *sync.SyncStorage - -func SetCachedStorage() error { - Storage = cache.NewCache( - storage.NewGenericStorage( - storage.NewDefaultRawStorage(constants.DATA_DIR), scheme.Serializer)) - return nil -} - -// TODO: Special ManifestStorage type -func SetManifestStorage() error { - ws, err := watch.NewGenericWatchStorage(storage.NewGenericStorage(raw.NewGenericMappedRawStorage("/etc/firecracker/manifests"), scheme.Serializer)) - if err != nil { - return err - } - - ss := sync.NewSyncStorage( - storage.NewGenericStorage(storage.NewDefaultRawStorage(constants.DATA_DIR), scheme.Serializer), - ws) - - SyncStorage = ss.(*sync.SyncStorage) - Storage = cache.NewCache(ss) - - return nil -} diff --git a/pkg/providers/storage/storage.go b/pkg/providers/storage/storage.go new file mode 100644 index 000000000..e46d2b5a8 --- /dev/null +++ b/pkg/providers/storage/storage.go @@ -0,0 +1,29 @@ +package providers + +import ( + log "github.com/sirupsen/logrus" + "github.com/weaveworks/ignite/pkg/apis/ignite/scheme" + "github.com/weaveworks/ignite/pkg/constants" + "github.com/weaveworks/ignite/pkg/providers" + "github.com/weaveworks/ignite/pkg/storage" + "github.com/weaveworks/ignite/pkg/storage/cache" + "github.com/weaveworks/ignite/pkg/storage/manifest" +) + +func SetGenericStorage() error { + log.Trace("Initializing the GenericStorage provider...") + providers.Storage = cache.NewCache( + storage.NewGenericStorage( + storage.NewDefaultRawStorage(constants.DATA_DIR), scheme.Serializer)) + return nil +} + +func SetManifestStorage() error { + log.Trace("Initializing the ManifestStorage provider...") + ms, err := manifest.NewManifestStorage("/etc/firecracker/manifests") + if err != nil { + return err + } + providers.Storage = cache.NewCache(ms) + return nil +} diff --git a/pkg/storage/cache/cache.go b/pkg/storage/cache/cache.go index 9157a1e70..6c9b9dfef 100644 --- a/pkg/storage/cache/cache.go +++ b/pkg/storage/cache/cache.go @@ -150,6 +150,10 @@ func (c *cache) RawStorage() storage.RawStorage { return c.storage.RawStorage() } +func (c *cache) Close() error { + return c.storage.Close() +} + func (c *cache) Flush() error { // Load the entire cache allObjects, err := c.index.loadAll() diff --git a/pkg/storage/storage.go b/pkg/storage/storage.go index 61122c60a..1cf65f2b4 100644 --- a/pkg/storage/storage.go +++ b/pkg/storage/storage.go @@ -44,6 +44,8 @@ type Storage interface { Checksum(gvk schema.GroupVersionKind, uid meta.UID) (string, error) // RawStorage returns the RawStorage instance backing this Storage RawStorage() RawStorage + // Close closes all underlying resources (e.g. goroutines) used; before the application exits + Close() error } // NewGenericStorage constructs a new Storage @@ -206,6 +208,11 @@ func (s *GenericStorage) RawStorage() RawStorage { return s.raw } +// Close closes all underlying resources (e.g. goroutines) used; before the application exits +func (s *GenericStorage) Close() error { + return nil // nothing to do here for GenericStorage +} + func (s *GenericStorage) decode(content []byte, gvk schema.GroupVersionKind) (meta.Object, error) { // Decode the bytes to the internal version of the Object, if desired isInternal := gvk.Version == runtime.APIVersionInternal diff --git a/pkg/storage/sync/storage.go b/pkg/storage/sync/storage.go index ffcc5d99d..f92236e32 100644 --- a/pkg/storage/sync/storage.go +++ b/pkg/storage/sync/storage.go @@ -84,7 +84,7 @@ func (ss *SyncStorage) Delete(gvk schema.GroupVersionKind, uid meta.UID) error { }) } -func (ss *SyncStorage) Close() { +func (ss *SyncStorage) Close() error { // Close all WatchStorages for _, s := range ss.storages { if watchStorage, ok := s.(watch.WatchStorage); ok { @@ -94,6 +94,7 @@ func (ss *SyncStorage) Close() { close(ss.eventStream) // Close the event stream ss.monitor.Wait() // Wait for the monitor goroutine + return nil } func (ss *SyncStorage) GetUpdateStream() UpdateStream { diff --git a/pkg/storage/watch/storage.go b/pkg/storage/watch/storage.go index 803980133..c60b973a8 100644 --- a/pkg/storage/watch/storage.go +++ b/pkg/storage/watch/storage.go @@ -27,8 +27,6 @@ type WatchStorage interface { storage.Storage // GetTrigger returns a hook that can be used to detect a watch event SetEventStream(AssociatedEventStream) - // Close is used to stop monitoring goroutines - Close() } type AssociatedEventStream chan update.AssociatedUpdate @@ -86,9 +84,10 @@ func (s *GenericWatchStorage) SetEventStream(eventStream AssociatedEventStream) s.events = &eventStream } -func (s *GenericWatchStorage) Close() { +func (s *GenericWatchStorage) Close() error { s.watcher.Close() s.monitor.Wait() + return nil } func (s *GenericWatchStorage) monitorFunc(mapped raw.MappedRawStorage, files []string) {