github.com/panekj/cli@v0.0.0-20230304125325-467dd2f3797e/cli/command/defaultcontextstore.go (about) 1 package command 2 3 import ( 4 "github.com/docker/cli/cli/context/docker" 5 "github.com/docker/cli/cli/context/store" 6 cliflags "github.com/docker/cli/cli/flags" 7 "github.com/docker/docker/errdefs" 8 "github.com/pkg/errors" 9 ) 10 11 const ( 12 // DefaultContextName is the name reserved for the default context (config & env based) 13 DefaultContextName = "default" 14 ) 15 16 // DefaultContext contains the default context data for all endpoints 17 type DefaultContext struct { 18 Meta store.Metadata 19 TLS store.ContextTLSData 20 } 21 22 // DefaultContextResolver is a function which resolves the default context base on the configuration and the env variables 23 type DefaultContextResolver func() (*DefaultContext, error) 24 25 // ContextStoreWithDefault implements the store.Store interface with a support for the default context 26 type ContextStoreWithDefault struct { 27 store.Store 28 Resolver DefaultContextResolver 29 } 30 31 // EndpointDefaultResolver is implemented by any EndpointMeta object 32 // which wants to be able to populate the store with whatever their default is. 33 type EndpointDefaultResolver interface { 34 // ResolveDefault returns values suitable for storing in store.Metadata.Endpoints 35 // and store.ContextTLSData.Endpoints. 36 // 37 // An error is only returned for something fatal, not simply 38 // the lack of a default (e.g. because the config file which 39 // would contain it is missing). If there is no default then 40 // returns nil, nil, nil. 41 ResolveDefault() (interface{}, *store.EndpointTLSData, error) 42 } 43 44 // ResolveDefaultContext creates a Metadata for the current CLI invocation parameters 45 func ResolveDefaultContext(opts *cliflags.ClientOptions, config store.Config) (*DefaultContext, error) { 46 contextTLSData := store.ContextTLSData{ 47 Endpoints: make(map[string]store.EndpointTLSData), 48 } 49 contextMetadata := store.Metadata{ 50 Endpoints: make(map[string]interface{}), 51 Metadata: DockerContext{ 52 Description: "", 53 }, 54 Name: DefaultContextName, 55 } 56 57 dockerEP, err := resolveDefaultDockerEndpoint(opts) 58 if err != nil { 59 return nil, err 60 } 61 contextMetadata.Endpoints[docker.DockerEndpoint] = dockerEP.EndpointMeta 62 if dockerEP.TLSData != nil { 63 contextTLSData.Endpoints[docker.DockerEndpoint] = *dockerEP.TLSData.ToStoreTLSData() 64 } 65 66 if err := config.ForeachEndpointType(func(n string, get store.TypeGetter) error { 67 if n == docker.DockerEndpoint { // handled above 68 return nil 69 } 70 ep := get() 71 if i, ok := ep.(EndpointDefaultResolver); ok { 72 meta, tls, err := i.ResolveDefault() 73 if err != nil { 74 return err 75 } 76 if meta == nil { 77 return nil 78 } 79 contextMetadata.Endpoints[n] = meta 80 if tls != nil { 81 contextTLSData.Endpoints[n] = *tls 82 } 83 } 84 // Nothing to be done 85 return nil 86 }); err != nil { 87 return nil, err 88 } 89 90 return &DefaultContext{Meta: contextMetadata, TLS: contextTLSData}, nil 91 } 92 93 // List implements store.Store's List 94 func (s *ContextStoreWithDefault) List() ([]store.Metadata, error) { 95 contextList, err := s.Store.List() 96 if err != nil { 97 return nil, err 98 } 99 defaultContext, err := s.Resolver() 100 if err != nil { 101 return nil, err 102 } 103 return append(contextList, defaultContext.Meta), nil 104 } 105 106 // CreateOrUpdate is not allowed for the default context and fails 107 func (s *ContextStoreWithDefault) CreateOrUpdate(meta store.Metadata) error { 108 if meta.Name == DefaultContextName { 109 return errdefs.InvalidParameter(errors.New("default context cannot be created nor updated")) 110 } 111 return s.Store.CreateOrUpdate(meta) 112 } 113 114 // Remove is not allowed for the default context and fails 115 func (s *ContextStoreWithDefault) Remove(name string) error { 116 if name == DefaultContextName { 117 return errdefs.InvalidParameter(errors.New("default context cannot be removed")) 118 } 119 return s.Store.Remove(name) 120 } 121 122 // GetMetadata implements store.Store's GetMetadata 123 func (s *ContextStoreWithDefault) GetMetadata(name string) (store.Metadata, error) { 124 if name == DefaultContextName { 125 defaultContext, err := s.Resolver() 126 if err != nil { 127 return store.Metadata{}, err 128 } 129 return defaultContext.Meta, nil 130 } 131 return s.Store.GetMetadata(name) 132 } 133 134 // ResetTLSMaterial is not implemented for default context and fails 135 func (s *ContextStoreWithDefault) ResetTLSMaterial(name string, data *store.ContextTLSData) error { 136 if name == DefaultContextName { 137 return errdefs.InvalidParameter(errors.New("default context cannot be edited")) 138 } 139 return s.Store.ResetTLSMaterial(name, data) 140 } 141 142 // ResetEndpointTLSMaterial is not implemented for default context and fails 143 func (s *ContextStoreWithDefault) ResetEndpointTLSMaterial(contextName string, endpointName string, data *store.EndpointTLSData) error { 144 if contextName == DefaultContextName { 145 return errdefs.InvalidParameter(errors.New("default context cannot be edited")) 146 } 147 return s.Store.ResetEndpointTLSMaterial(contextName, endpointName, data) 148 } 149 150 // ListTLSFiles implements store.Store's ListTLSFiles 151 func (s *ContextStoreWithDefault) ListTLSFiles(name string) (map[string]store.EndpointFiles, error) { 152 if name == DefaultContextName { 153 defaultContext, err := s.Resolver() 154 if err != nil { 155 return nil, err 156 } 157 tlsfiles := make(map[string]store.EndpointFiles) 158 for epName, epTLSData := range defaultContext.TLS.Endpoints { 159 var files store.EndpointFiles 160 for filename := range epTLSData.Files { 161 files = append(files, filename) 162 } 163 tlsfiles[epName] = files 164 } 165 return tlsfiles, nil 166 } 167 return s.Store.ListTLSFiles(name) 168 } 169 170 // GetTLSData implements store.Store's GetTLSData 171 func (s *ContextStoreWithDefault) GetTLSData(contextName, endpointName, fileName string) ([]byte, error) { 172 if contextName == DefaultContextName { 173 defaultContext, err := s.Resolver() 174 if err != nil { 175 return nil, err 176 } 177 if defaultContext.TLS.Endpoints[endpointName].Files[fileName] == nil { 178 return nil, errdefs.NotFound(errors.Errorf("TLS data for %s/%s/%s does not exist", DefaultContextName, endpointName, fileName)) 179 } 180 return defaultContext.TLS.Endpoints[endpointName].Files[fileName], nil 181 } 182 return s.Store.GetTLSData(contextName, endpointName, fileName) 183 } 184 185 // GetStorageInfo implements store.Store's GetStorageInfo 186 func (s *ContextStoreWithDefault) GetStorageInfo(contextName string) store.StorageInfo { 187 if contextName == DefaultContextName { 188 return store.StorageInfo{MetadataPath: "<IN MEMORY>", TLSPath: "<IN MEMORY>"} 189 } 190 return s.Store.GetStorageInfo(contextName) 191 }