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