github.com/rish1988/moby@v25.0.2+incompatible/registry/registry_test.go (about)

     1  package registry // import "github.com/docker/docker/registry"
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/distribution/reference"
     7  	"github.com/docker/docker/api/types/registry"
     8  	"gotest.tools/v3/assert"
     9  	is "gotest.tools/v3/assert/cmp"
    10  )
    11  
    12  func TestParseRepositoryInfo(t *testing.T) {
    13  	type staticRepositoryInfo struct {
    14  		Index         *registry.IndexInfo
    15  		RemoteName    string
    16  		CanonicalName string
    17  		LocalName     string
    18  		Official      bool
    19  	}
    20  
    21  	expectedRepoInfos := map[string]staticRepositoryInfo{
    22  		"fooo/bar": {
    23  			Index: &registry.IndexInfo{
    24  				Name:     IndexName,
    25  				Official: true,
    26  			},
    27  			RemoteName:    "fooo/bar",
    28  			LocalName:     "fooo/bar",
    29  			CanonicalName: "docker.io/fooo/bar",
    30  			Official:      false,
    31  		},
    32  		"library/ubuntu": {
    33  			Index: &registry.IndexInfo{
    34  				Name:     IndexName,
    35  				Official: true,
    36  			},
    37  			RemoteName:    "library/ubuntu",
    38  			LocalName:     "ubuntu",
    39  			CanonicalName: "docker.io/library/ubuntu",
    40  			Official:      true,
    41  		},
    42  		"nonlibrary/ubuntu": {
    43  			Index: &registry.IndexInfo{
    44  				Name:     IndexName,
    45  				Official: true,
    46  			},
    47  			RemoteName:    "nonlibrary/ubuntu",
    48  			LocalName:     "nonlibrary/ubuntu",
    49  			CanonicalName: "docker.io/nonlibrary/ubuntu",
    50  			Official:      false,
    51  		},
    52  		"ubuntu": {
    53  			Index: &registry.IndexInfo{
    54  				Name:     IndexName,
    55  				Official: true,
    56  			},
    57  			RemoteName:    "library/ubuntu",
    58  			LocalName:     "ubuntu",
    59  			CanonicalName: "docker.io/library/ubuntu",
    60  			Official:      true,
    61  		},
    62  		"other/library": {
    63  			Index: &registry.IndexInfo{
    64  				Name:     IndexName,
    65  				Official: true,
    66  			},
    67  			RemoteName:    "other/library",
    68  			LocalName:     "other/library",
    69  			CanonicalName: "docker.io/other/library",
    70  			Official:      false,
    71  		},
    72  		"127.0.0.1:8000/private/moonbase": {
    73  			Index: &registry.IndexInfo{
    74  				Name:     "127.0.0.1:8000",
    75  				Official: false,
    76  			},
    77  			RemoteName:    "private/moonbase",
    78  			LocalName:     "127.0.0.1:8000/private/moonbase",
    79  			CanonicalName: "127.0.0.1:8000/private/moonbase",
    80  			Official:      false,
    81  		},
    82  		"127.0.0.1:8000/privatebase": {
    83  			Index: &registry.IndexInfo{
    84  				Name:     "127.0.0.1:8000",
    85  				Official: false,
    86  			},
    87  			RemoteName:    "privatebase",
    88  			LocalName:     "127.0.0.1:8000/privatebase",
    89  			CanonicalName: "127.0.0.1:8000/privatebase",
    90  			Official:      false,
    91  		},
    92  		"localhost:8000/private/moonbase": {
    93  			Index: &registry.IndexInfo{
    94  				Name:     "localhost:8000",
    95  				Official: false,
    96  			},
    97  			RemoteName:    "private/moonbase",
    98  			LocalName:     "localhost:8000/private/moonbase",
    99  			CanonicalName: "localhost:8000/private/moonbase",
   100  			Official:      false,
   101  		},
   102  		"localhost:8000/privatebase": {
   103  			Index: &registry.IndexInfo{
   104  				Name:     "localhost:8000",
   105  				Official: false,
   106  			},
   107  			RemoteName:    "privatebase",
   108  			LocalName:     "localhost:8000/privatebase",
   109  			CanonicalName: "localhost:8000/privatebase",
   110  			Official:      false,
   111  		},
   112  		"example.com/private/moonbase": {
   113  			Index: &registry.IndexInfo{
   114  				Name:     "example.com",
   115  				Official: false,
   116  			},
   117  			RemoteName:    "private/moonbase",
   118  			LocalName:     "example.com/private/moonbase",
   119  			CanonicalName: "example.com/private/moonbase",
   120  			Official:      false,
   121  		},
   122  		"example.com/privatebase": {
   123  			Index: &registry.IndexInfo{
   124  				Name:     "example.com",
   125  				Official: false,
   126  			},
   127  			RemoteName:    "privatebase",
   128  			LocalName:     "example.com/privatebase",
   129  			CanonicalName: "example.com/privatebase",
   130  			Official:      false,
   131  		},
   132  		"example.com:8000/private/moonbase": {
   133  			Index: &registry.IndexInfo{
   134  				Name:     "example.com:8000",
   135  				Official: false,
   136  			},
   137  			RemoteName:    "private/moonbase",
   138  			LocalName:     "example.com:8000/private/moonbase",
   139  			CanonicalName: "example.com:8000/private/moonbase",
   140  			Official:      false,
   141  		},
   142  		"example.com:8000/privatebase": {
   143  			Index: &registry.IndexInfo{
   144  				Name:     "example.com:8000",
   145  				Official: false,
   146  			},
   147  			RemoteName:    "privatebase",
   148  			LocalName:     "example.com:8000/privatebase",
   149  			CanonicalName: "example.com:8000/privatebase",
   150  			Official:      false,
   151  		},
   152  		"localhost/private/moonbase": {
   153  			Index: &registry.IndexInfo{
   154  				Name:     "localhost",
   155  				Official: false,
   156  			},
   157  			RemoteName:    "private/moonbase",
   158  			LocalName:     "localhost/private/moonbase",
   159  			CanonicalName: "localhost/private/moonbase",
   160  			Official:      false,
   161  		},
   162  		"localhost/privatebase": {
   163  			Index: &registry.IndexInfo{
   164  				Name:     "localhost",
   165  				Official: false,
   166  			},
   167  			RemoteName:    "privatebase",
   168  			LocalName:     "localhost/privatebase",
   169  			CanonicalName: "localhost/privatebase",
   170  			Official:      false,
   171  		},
   172  		IndexName + "/public/moonbase": {
   173  			Index: &registry.IndexInfo{
   174  				Name:     IndexName,
   175  				Official: true,
   176  			},
   177  			RemoteName:    "public/moonbase",
   178  			LocalName:     "public/moonbase",
   179  			CanonicalName: "docker.io/public/moonbase",
   180  			Official:      false,
   181  		},
   182  		"index." + IndexName + "/public/moonbase": {
   183  			Index: &registry.IndexInfo{
   184  				Name:     IndexName,
   185  				Official: true,
   186  			},
   187  			RemoteName:    "public/moonbase",
   188  			LocalName:     "public/moonbase",
   189  			CanonicalName: "docker.io/public/moonbase",
   190  			Official:      false,
   191  		},
   192  		"ubuntu-12.04-base": {
   193  			Index: &registry.IndexInfo{
   194  				Name:     IndexName,
   195  				Official: true,
   196  			},
   197  			RemoteName:    "library/ubuntu-12.04-base",
   198  			LocalName:     "ubuntu-12.04-base",
   199  			CanonicalName: "docker.io/library/ubuntu-12.04-base",
   200  			Official:      true,
   201  		},
   202  		IndexName + "/ubuntu-12.04-base": {
   203  			Index: &registry.IndexInfo{
   204  				Name:     IndexName,
   205  				Official: true,
   206  			},
   207  			RemoteName:    "library/ubuntu-12.04-base",
   208  			LocalName:     "ubuntu-12.04-base",
   209  			CanonicalName: "docker.io/library/ubuntu-12.04-base",
   210  			Official:      true,
   211  		},
   212  		"index." + IndexName + "/ubuntu-12.04-base": {
   213  			Index: &registry.IndexInfo{
   214  				Name:     IndexName,
   215  				Official: true,
   216  			},
   217  			RemoteName:    "library/ubuntu-12.04-base",
   218  			LocalName:     "ubuntu-12.04-base",
   219  			CanonicalName: "docker.io/library/ubuntu-12.04-base",
   220  			Official:      true,
   221  		},
   222  	}
   223  
   224  	for reposName, expectedRepoInfo := range expectedRepoInfos {
   225  		named, err := reference.ParseNormalizedNamed(reposName)
   226  		if err != nil {
   227  			t.Error(err)
   228  		}
   229  
   230  		repoInfo, err := ParseRepositoryInfo(named)
   231  		if err != nil {
   232  			t.Error(err)
   233  		} else {
   234  			assert.Check(t, is.Equal(repoInfo.Index.Name, expectedRepoInfo.Index.Name), reposName)
   235  			assert.Check(t, is.Equal(reference.Path(repoInfo.Name), expectedRepoInfo.RemoteName), reposName)
   236  			assert.Check(t, is.Equal(reference.FamiliarName(repoInfo.Name), expectedRepoInfo.LocalName), reposName)
   237  			assert.Check(t, is.Equal(repoInfo.Name.Name(), expectedRepoInfo.CanonicalName), reposName)
   238  			assert.Check(t, is.Equal(repoInfo.Index.Official, expectedRepoInfo.Index.Official), reposName)
   239  			assert.Check(t, is.Equal(repoInfo.Official, expectedRepoInfo.Official), reposName)
   240  		}
   241  	}
   242  }
   243  
   244  func TestNewIndexInfo(t *testing.T) {
   245  	testIndexInfo := func(config *serviceConfig, expectedIndexInfos map[string]*registry.IndexInfo) {
   246  		for indexName, expectedIndexInfo := range expectedIndexInfos {
   247  			index, err := newIndexInfo(config, indexName)
   248  			if err != nil {
   249  				t.Fatal(err)
   250  			} else {
   251  				assert.Check(t, is.Equal(index.Name, expectedIndexInfo.Name), indexName+" name")
   252  				assert.Check(t, is.Equal(index.Official, expectedIndexInfo.Official), indexName+" is official")
   253  				assert.Check(t, is.Equal(index.Secure, expectedIndexInfo.Secure), indexName+" is secure")
   254  				assert.Check(t, is.Equal(len(index.Mirrors), len(expectedIndexInfo.Mirrors)), indexName+" mirrors")
   255  			}
   256  		}
   257  	}
   258  
   259  	config := emptyServiceConfig
   260  	var noMirrors []string
   261  	expectedIndexInfos := map[string]*registry.IndexInfo{
   262  		IndexName: {
   263  			Name:     IndexName,
   264  			Official: true,
   265  			Secure:   true,
   266  			Mirrors:  noMirrors,
   267  		},
   268  		"index." + IndexName: {
   269  			Name:     IndexName,
   270  			Official: true,
   271  			Secure:   true,
   272  			Mirrors:  noMirrors,
   273  		},
   274  		"example.com": {
   275  			Name:     "example.com",
   276  			Official: false,
   277  			Secure:   true,
   278  			Mirrors:  noMirrors,
   279  		},
   280  		"127.0.0.1:5000": {
   281  			Name:     "127.0.0.1:5000",
   282  			Official: false,
   283  			Secure:   false,
   284  			Mirrors:  noMirrors,
   285  		},
   286  	}
   287  	testIndexInfo(config, expectedIndexInfos)
   288  
   289  	publicMirrors := []string{"http://mirror1.local", "http://mirror2.local"}
   290  	var err error
   291  	config, err = makeServiceConfig(publicMirrors, []string{"example.com"})
   292  	if err != nil {
   293  		t.Fatal(err)
   294  	}
   295  
   296  	expectedIndexInfos = map[string]*registry.IndexInfo{
   297  		IndexName: {
   298  			Name:     IndexName,
   299  			Official: true,
   300  			Secure:   true,
   301  			Mirrors:  publicMirrors,
   302  		},
   303  		"index." + IndexName: {
   304  			Name:     IndexName,
   305  			Official: true,
   306  			Secure:   true,
   307  			Mirrors:  publicMirrors,
   308  		},
   309  		"example.com": {
   310  			Name:     "example.com",
   311  			Official: false,
   312  			Secure:   false,
   313  			Mirrors:  noMirrors,
   314  		},
   315  		"example.com:5000": {
   316  			Name:     "example.com:5000",
   317  			Official: false,
   318  			Secure:   true,
   319  			Mirrors:  noMirrors,
   320  		},
   321  		"127.0.0.1": {
   322  			Name:     "127.0.0.1",
   323  			Official: false,
   324  			Secure:   false,
   325  			Mirrors:  noMirrors,
   326  		},
   327  		"127.0.0.1:5000": {
   328  			Name:     "127.0.0.1:5000",
   329  			Official: false,
   330  			Secure:   false,
   331  			Mirrors:  noMirrors,
   332  		},
   333  		"other.com": {
   334  			Name:     "other.com",
   335  			Official: false,
   336  			Secure:   true,
   337  			Mirrors:  noMirrors,
   338  		},
   339  	}
   340  	testIndexInfo(config, expectedIndexInfos)
   341  
   342  	config, err = makeServiceConfig(nil, []string{"42.42.0.0/16"})
   343  	if err != nil {
   344  		t.Fatal(err)
   345  	}
   346  	expectedIndexInfos = map[string]*registry.IndexInfo{
   347  		"example.com": {
   348  			Name:     "example.com",
   349  			Official: false,
   350  			Secure:   false,
   351  			Mirrors:  noMirrors,
   352  		},
   353  		"example.com:5000": {
   354  			Name:     "example.com:5000",
   355  			Official: false,
   356  			Secure:   false,
   357  			Mirrors:  noMirrors,
   358  		},
   359  		"127.0.0.1": {
   360  			Name:     "127.0.0.1",
   361  			Official: false,
   362  			Secure:   false,
   363  			Mirrors:  noMirrors,
   364  		},
   365  		"127.0.0.1:5000": {
   366  			Name:     "127.0.0.1:5000",
   367  			Official: false,
   368  			Secure:   false,
   369  			Mirrors:  noMirrors,
   370  		},
   371  		"other.com": {
   372  			Name:     "other.com",
   373  			Official: false,
   374  			Secure:   true,
   375  			Mirrors:  noMirrors,
   376  		},
   377  	}
   378  	testIndexInfo(config, expectedIndexInfos)
   379  }
   380  
   381  func TestMirrorEndpointLookup(t *testing.T) {
   382  	containsMirror := func(endpoints []APIEndpoint) bool {
   383  		for _, pe := range endpoints {
   384  			if pe.URL.Host == "my.mirror" {
   385  				return true
   386  			}
   387  		}
   388  		return false
   389  	}
   390  	cfg, err := makeServiceConfig([]string{"https://my.mirror"}, nil)
   391  	if err != nil {
   392  		t.Fatal(err)
   393  	}
   394  	s := Service{config: cfg}
   395  
   396  	imageName, err := reference.WithName(IndexName + "/test/image")
   397  	if err != nil {
   398  		t.Error(err)
   399  	}
   400  	pushAPIEndpoints, err := s.LookupPushEndpoints(reference.Domain(imageName))
   401  	if err != nil {
   402  		t.Fatal(err)
   403  	}
   404  	if containsMirror(pushAPIEndpoints) {
   405  		t.Fatal("Push endpoint should not contain mirror")
   406  	}
   407  
   408  	pullAPIEndpoints, err := s.LookupPullEndpoints(reference.Domain(imageName))
   409  	if err != nil {
   410  		t.Fatal(err)
   411  	}
   412  	if !containsMirror(pullAPIEndpoints) {
   413  		t.Fatal("Pull endpoint should contain mirror")
   414  	}
   415  }
   416  
   417  func TestAllowNondistributableArtifacts(t *testing.T) {
   418  	tests := []struct {
   419  		addr       string
   420  		registries []string
   421  		expected   bool
   422  	}{
   423  		{IndexName, nil, false},
   424  		{"example.com", []string{}, false},
   425  		{"example.com", []string{"example.com"}, true},
   426  		{"localhost", []string{"localhost:5000"}, false},
   427  		{"localhost:5000", []string{"localhost:5000"}, true},
   428  		{"localhost", []string{"example.com"}, false},
   429  		{"127.0.0.1:5000", []string{"127.0.0.1:5000"}, true},
   430  		{"localhost", nil, false},
   431  		{"localhost:5000", nil, false},
   432  		{"127.0.0.1", nil, false},
   433  		{"localhost", []string{"example.com"}, false},
   434  		{"127.0.0.1", []string{"example.com"}, false},
   435  		{"example.com", nil, false},
   436  		{"example.com", []string{"example.com"}, true},
   437  		{"127.0.0.1", []string{"example.com"}, false},
   438  		{"127.0.0.1:5000", []string{"example.com"}, false},
   439  		{"example.com:5000", []string{"42.42.0.0/16"}, true},
   440  		{"example.com", []string{"42.42.0.0/16"}, true},
   441  		{"example.com:5000", []string{"42.42.42.42/8"}, true},
   442  		{"127.0.0.1:5000", []string{"127.0.0.0/8"}, true},
   443  		{"42.42.42.42:5000", []string{"42.1.1.1/8"}, true},
   444  		{"invalid.example.com", []string{"42.42.0.0/16"}, false},
   445  		{"invalid.example.com", []string{"invalid.example.com"}, true},
   446  		{"invalid.example.com:5000", []string{"invalid.example.com"}, false},
   447  		{"invalid.example.com:5000", []string{"invalid.example.com:5000"}, true},
   448  	}
   449  	for _, tt := range tests {
   450  		config, err := newServiceConfig(ServiceOptions{
   451  			AllowNondistributableArtifacts: tt.registries,
   452  		})
   453  		if err != nil {
   454  			t.Error(err)
   455  		}
   456  		if v := config.allowNondistributableArtifacts(tt.addr); v != tt.expected {
   457  			t.Errorf("allowNondistributableArtifacts failed for %q %v, expected %v got %v", tt.addr, tt.registries, tt.expected, v)
   458  		}
   459  	}
   460  }
   461  
   462  func TestIsSecureIndex(t *testing.T) {
   463  	tests := []struct {
   464  		addr               string
   465  		insecureRegistries []string
   466  		expected           bool
   467  	}{
   468  		{IndexName, nil, true},
   469  		{"example.com", []string{}, true},
   470  		{"example.com", []string{"example.com"}, false},
   471  		{"localhost", []string{"localhost:5000"}, false},
   472  		{"localhost:5000", []string{"localhost:5000"}, false},
   473  		{"localhost", []string{"example.com"}, false},
   474  		{"127.0.0.1:5000", []string{"127.0.0.1:5000"}, false},
   475  		{"localhost", nil, false},
   476  		{"localhost:5000", nil, false},
   477  		{"127.0.0.1", nil, false},
   478  		{"localhost", []string{"example.com"}, false},
   479  		{"127.0.0.1", []string{"example.com"}, false},
   480  		{"example.com", nil, true},
   481  		{"example.com", []string{"example.com"}, false},
   482  		{"127.0.0.1", []string{"example.com"}, false},
   483  		{"127.0.0.1:5000", []string{"example.com"}, false},
   484  		{"example.com:5000", []string{"42.42.0.0/16"}, false},
   485  		{"example.com", []string{"42.42.0.0/16"}, false},
   486  		{"example.com:5000", []string{"42.42.42.42/8"}, false},
   487  		{"127.0.0.1:5000", []string{"127.0.0.0/8"}, false},
   488  		{"42.42.42.42:5000", []string{"42.1.1.1/8"}, false},
   489  		{"invalid.example.com", []string{"42.42.0.0/16"}, true},
   490  		{"invalid.example.com", []string{"invalid.example.com"}, false},
   491  		{"invalid.example.com:5000", []string{"invalid.example.com"}, true},
   492  		{"invalid.example.com:5000", []string{"invalid.example.com:5000"}, false},
   493  	}
   494  	for _, tt := range tests {
   495  		config, err := makeServiceConfig(nil, tt.insecureRegistries)
   496  		if err != nil {
   497  			t.Error(err)
   498  		}
   499  		if sec := config.isSecureIndex(tt.addr); sec != tt.expected {
   500  			t.Errorf("isSecureIndex failed for %q %v, expected %v got %v", tt.addr, tt.insecureRegistries, tt.expected, sec)
   501  		}
   502  	}
   503  }