Project

General

Profile

Revision 329cfcba

Added by Sebastian Gräßl about 5 years ago

Fixes #18902 - Enable autocomplete for container image search

This enables the autocomplete for the image name search and
improves the usability of searching for container images on
Docker Hub or an external Registry.

View differences:

test/functionals/image_search_controller_test.rb
18 18
      .stubs(:find).returns(registry)
19 19
  end
20 20

  
21
  describe '#auto_complete_repository_name' do
22
    test 'returns if an image is available' do
23
      exists = ['true', 'false'].sample
24
      search_type = ['hub', 'registry'].sample
25
      subject.instance_variable_set(:@image_search_service, image_search_service)
26
      image_search_service.expects(:available?).returns(exists)
27

  
28
      xhr :get, :auto_complete_repository_name,
29
        { registry: search_type, search: term,
30
          id: compute_resource }, set_session_user
31
      assert_equal exists, response.body
32
    end
33

  
34
    context 'it is a Docker Hub tab request' do
35
      let(:search_type) { 'hub' }
21
  describe '#search_repository' do
22
    let(:search_types) { ['hub', 'registry'] }
36 23

  
37
      test 'it queries the compute_resource and Docker Hub' do
38
        compute_resource.expects(:image).with(term)
39
          .returns(term)
40
        compute_resource.expects(:tags_for_local_image)
41
          .returns(tags)
42
        docker_hub.expects(:tags).returns([])
24
    describe 'calls #search on image_search_service' do
25
      setup do
26
        subject.instance_variable_set(:@image_search_service, image_search_service)
27
      end
43 28

  
44
        xhr :get, :auto_complete_repository_name,
45
          { registry: search_type, search: term,
29
      test 'passes params search and tags' do
30
        tags_enabled = ['true', 'false'].sample
31
        image_search_service.expects(:search).with({ term: term, tags: tags_enabled })
32
          .returns([])
33
        xhr :get, :search_repository,
34
          { registry: search_types.sample, search: term, tags: tags_enabled,
46 35
            id: compute_resource }, set_session_user
47 36
      end
48
    end
49

  
50
    context 'it is a External Registry tab request' do
51
      let(:search_type) { 'registry' }
52 37

  
53
      test 'it only queries the registry api' do
54
        compute_resource.expects(:image).with(term).never
55
        docker_hub.expects(:tags).never
56
        registry.api.expects(:tags).with(term, nil)
57
          .returns(['latest'])
38
      test 'returns an array of { label:, value: } hashes' do
39
        image_search_service.expects(:search).with({ term: term, tags: 'true' })
40
          .returns(tags)
41
        xhr :get, :search_repository,
42
          { registry: search_types.sample, search: term, tags: 'true',
43
            id: compute_resource }, set_session_user
44
        assert_equal tags.first, JSON.parse(response.body).first['value']
45
      end
58 46

  
59
        xhr :get, :auto_complete_repository_name,
60
          { registry: search_type, registry_id: registry,
61
            search: term, id: compute_resource }, set_session_user
47
      test 'returns html with the found images' do
48
        image_search_service.expects(:search)
49
          .with({ term: term, tags: 'false' })
50
          .returns([{ 'name' => term }])
51
        xhr :get, :search_repository,
52
          { registry: search_types.sample, search: term,
53
            id: compute_resource, format: :html}, set_session_user
54
        assert response.body.include?(term)
62 55
      end
63
    end
64
  end
65 56

  
66
  describe '#auto_complete_image_tag' do
67
    let(:tag_fragment) { 'lat' }
68
    let(:term) { "#{docker_image}:#{tag_fragment}"}
69

  
70
    test 'returns an array of { label:, value: } hashes' do
71
      search_type = ['hub', 'registry'].sample
72
      subject.instance_variable_set(:@image_search_service, image_search_service)
73
      image_search_service.expects(:search)
74
        .with({ term: term, tags: 'true' })
75
        .returns(tags)
76
      xhr :get, :auto_complete_image_tag,
77
        { registry: search_type, search: term,
78
          id: compute_resource }, set_session_user
79
      assert_equal tags.first, JSON.parse(response.body).first['value']
80
    end
57
      [Docker::Error::DockerError, Excon::Errors::Error, Errno::ECONNREFUSED].each do |error|
58
        test "search_repository catch exceptions on network errors like #{error}" do
59
          image_search_service.expects(:search)
60
            .raises(error)
61
          xhr :get, :search_repository,
62
            { registry: search_types.sample, search: term, id: compute_resource }, set_session_user
81 63

  
82
    context 'a Docker Hub tab request' do
83
      let(:search_type) { 'hub' }
64
          assert_response :error
65
          assert response.body.include?('An error occured during repository search:')
66
        end
67
      end
84 68

  
85
      test 'it searches Docker Hub and the ComputeResource' do
86
        compute_resource.expects(:image).with(docker_image)
87
          .returns(term)
88
        compute_resource.expects(:tags_for_local_image)
89
          .returns(tags)
90
        docker_hub.expects(:tags).returns([])
69
      test "centos 7 search responses are handled correctly" do
70
        repository = "registry-fancycorp.rhcloud.com/fancydb-rhel7/fancydb"
71
        repo_full_name = "redhat.com: #{repository}"
72
        expected = [{  "description" => "Really fancy database app...",
73
                       "is_official" => true,
74
                       "is_trusted" => true,
75
                       "name" =>  repo_full_name,
76
                       "star_count" => 0
77
                    }]
78
        image_search_service.expects(:search).returns(expected)
79
        xhr :get, :search_repository,
80
          { registry: search_types.sample, search: 'centos', id: compute_resource, format: :html }, set_session_user
81
        assert_response :success
82
        refute response.body.include?(repo_full_name)
83
        assert response.body.include?(repository)
84
      end
91 85

  
92
        xhr :get, :auto_complete_image_tag,
93
          { registry: search_type, search: term,
94
            id: compute_resource }, set_session_user
86
      test "fedora search responses are handled correctly" do
87
        repository = "registry-fancycorp.rhcloud.com/fancydb-rhel7/fancydb"
88
        repo_full_name = repository
89
        request.env["HTTP_ACCEPT"] = "application/javascript"
90
        expected = [{ "description" => "Really fancy database app...",
91
                      "is_official" => true,
92
                      "is_trusted" => true,
93
                      "name" =>  repo_full_name,
94
                      "star_count" => 0
95
                    }]
96
        image_search_service.expects(:search).returns(expected)
97
        xhr :get, :search_repository,
98
          { registry: search_types.sample, search: term, id: compute_resource, format: :html }, set_session_user
99
        assert_response :success
100
        assert response.body.include?(repo_full_name)
101
        assert response.body.include?(repository)
95 102
      end
96 103
    end
97 104

  
98
    context 'it is a External Registry tab request' do
99
      let(:search_type) { 'registry' }
105
    describe 'for image names' do
106
      context 'with a Docker Hub tab request' do
107
        let(:search_type) { 'hub' }
100 108

  
101
      test 'it only queries the registry api' do
102
        compute_resource.expects(:image).with(docker_image).never
103
        docker_hub.expects(:tags).never
104
        registry.api.expects(:tags).with(docker_image, tag_fragment)
105
          .returns([])
109
        test 'it searches Docker Hub and the ComputeResource' do
110
          compute_resource.expects(:local_images)
111
            .returns([OpenStruct.new(info: { 'RepoTags' => [term] })])
112
          docker_hub.expects(:search).returns({})
106 113

  
107
        xhr :get, :auto_complete_image_tag,
108
          { registry: search_type, registry_id: registry,
109
            search: term, id: compute_resource }, set_session_user
114
          xhr :get, :search_repository,
115
            { registry: search_type, search: term,
116
              id: compute_resource }, set_session_user
117
        end
110 118
      end
111
    end
112
  end
113 119

  
114
  describe '#search_repository' do
115
    test 'returns html with the found images' do
116
      search_type = ['hub', 'registry'].sample
117
      subject.instance_variable_set(:@image_search_service, image_search_service)
118
      image_search_service.expects(:search)
119
        .with({ term: term, tags: 'false' })
120
        .returns([{ 'name' => term}])
121
      xhr :get, :search_repository,
122
        { registry: search_type, search: term,
123
          id: compute_resource }, set_session_user
124
      assert response.body.include?(term)
125
    end
120
      context 'with a External Registry tab request' do
121
        let(:search_type) { 'registry' }
126 122

  
127
    context 'a Docker Hub tab request' do
128
      let(:search_type) { 'hub' }
123
        test 'it only queries the registry api' do
124
          compute_resource.expects(:local_images).with(docker_image).never
125
          docker_hub.expects(:search).never
126
          registry.api.expects(:search).with(docker_image)
127
            .returns({})
129 128

  
130
      test 'it searches Docker Hub and the ComputeResource' do
131
        compute_resource.expects(:local_images)
132
          .returns([OpenStruct.new(info: { 'RepoTags' => [term] })])
133
        docker_hub.expects(:search).returns({})
134

  
135
        xhr :get, :search_repository,
136
          { registry: search_type, search: term,
137
            id: compute_resource }, set_session_user
129
          xhr :get, :search_repository,
130
            { registry: search_type, registry_id: registry,
131
              search: term, id: compute_resource }, set_session_user
132
        end
138 133
      end
139 134
    end
140 135

  
141
    context 'it is a External Registry tab request' do
142
      let(:search_type) { 'registry' }
136
    describe 'for tags' do
137
      let(:tag_fragment) { 'lat' }
138
      let(:term) { "#{docker_image}:#{tag_fragment}"}
143 139

  
144
      test 'it only queries the registry api' do
145
        compute_resource.expects(:local_images).with(docker_image).never
146
        docker_hub.expects(:search).never
147
        registry.api.expects(:search).with(docker_image)
148
          .returns({})
140
      context 'with a Docker Hub tab request' do
141
        let(:search_type) { 'hub' }
149 142

  
150
        xhr :get, :search_repository,
151
          { registry: search_type, registry_id: registry,
152
            search: term, id: compute_resource }, set_session_user
143
        test 'it searches Docker Hub and the ComputeResource' do
144
          compute_resource.expects(:image).with(docker_image)
145
            .returns(term)
146
          compute_resource.expects(:tags_for_local_image)
147
            .returns(tags)
148
          docker_hub.expects(:tags).returns([])
149

  
150
          xhr :get, :search_repository,
151
            { registry: search_type, search: term, tags: 'true',
152
              id: compute_resource }, set_session_user
153
        end
153 154
      end
154
    end
155
  end
156 155

  
157
  [Docker::Error::DockerError, Excon::Errors::Error, Errno::ECONNREFUSED].each do |error|
158
    test 'auto_complete_repository_name catches exceptions on network errors' do
159
      ForemanDocker::ImageSearch.any_instance.expects(:available?)
160
        .raises(error)
161
      xhr :get, :auto_complete_repository_name,
162
        { registry: 'hub', search: term, id: compute_resource }, set_session_user
163
      assert_response_is_expected
164
    end
156
      context 'with a External Registry tab request' do
157
        let(:search_type) { 'registry' }
165 158

  
166
    test 'auto_complete_image_tag catch exceptions on network errors' do
167
      ForemanDocker::ImageSearch.any_instance.expects(:search).raises(error)
168
      xhr :get, :auto_complete_image_tag,
169
        { registry: 'hub', search:  term, id: compute_resource }, set_session_user
170
      assert_response_is_expected
171
    end
159
        test 'it only queries the registry api' do
160
          compute_resource.expects(:image).with(docker_image).never
161
          docker_hub.expects(:tags).never
162
          registry.api.expects(:tags).with(docker_image, tag_fragment)
163
            .returns([])
172 164

  
173
    test 'search_repository catch exceptions on network errors' do
174
      ForemanDocker::ImageSearch.any_instance.expects(:search).raises(error)
175
      xhr :get, :search_repository,
176
        { registry: 'hub', search: term, id: compute_resource }, set_session_user
177
      assert_response_is_expected
165
          xhr :get, :search_repository,
166
            { registry: search_type, registry_id: registry, tags: 'true',
167
              search: term, id: compute_resource }, set_session_user
168
        end
169
      end
178 170
    end
179 171
  end
180

  
181
  test "centos 7 search responses are handled correctly" do
182
    repository = "registry-fancycorp.rhcloud.com/fancydb-rhel7/fancydb"
183
    repo_full_name = "redhat.com: #{repository}"
184
    request.env["HTTP_ACCEPT"] = "application/javascript"
185
    expected = [{  "description" => "Really fancy database app...",
186
                   "is_official" => true,
187
                   "is_trusted" => true,
188
                   "name" =>  repo_full_name,
189
                   "star_count" => 0
190
                }]
191
    ForemanDocker::ImageSearch.any_instance.expects(:search).returns(expected).at_least_once
192
    xhr :get, :search_repository,
193
      { registry: 'hub', search: 'centos', id: compute_resource }, set_session_user
194
    assert_response :success
195
    refute response.body.include?(repo_full_name)
196
    assert response.body.include?(repository)
197
  end
198

  
199
  test "fedora search responses are handled correctly" do
200
    repository = "registry-fancycorp.rhcloud.com/fancydb-rhel7/fancydb"
201
    repo_full_name = repository
202
    request.env["HTTP_ACCEPT"] = "application/javascript"
203
    expected = [{ "description" => "Really fancy database app...",
204
                  "is_official" => true,
205
                  "is_trusted" => true,
206
                  "name" =>  repo_full_name,
207
                  "star_count" => 0
208
                }]
209
    ForemanDocker::ImageSearch.any_instance.expects(:search).returns(expected).at_least_once
210
    xhr :get, :search_repository,
211
      { registry: 'hub', search: 'centos', id: compute_resource  }, set_session_user
212
    assert_response :success
213
    assert response.body.include?(repo_full_name)
214
    assert response.body.include?(repository)
215
  end
216

  
217
  def assert_response_is_expected
218
    assert_response :error
219
    assert response.body.include?('An error occured during repository search:')
220
  end
221 172
end

Also available in: Unified diff