1+ using Microsoft . AspNetCore . Mvc ;
2+
3+ using Moq ;
4+
5+ using Nullinside . Api . Common . Docker ;
6+ using Nullinside . Api . Common . Docker . Support ;
7+ using Nullinside . Api . Controllers ;
8+ using Nullinside . Api . Model . Ddl ;
9+ using Nullinside . Api . Shared . Json ;
10+
11+ namespace Nullinside . Api . Tests . Nullinside . Api . Controllers ;
12+
13+ /// <summary>
14+ /// Tests for the <see cref="DockerController" /> class
15+ /// </summary>
16+ public class DockerControllerTests : UnitTestBase {
17+ /// <summary>
18+ /// The docker proxy.
19+ /// </summary>
20+ private Mock < IDockerProxy > _docker ;
21+
22+ /// <summary>
23+ /// Add the docker proxy.
24+ /// </summary>
25+ public override void Setup ( ) {
26+ base . Setup ( ) ;
27+ _docker = new Mock < IDockerProxy > ( ) ;
28+ }
29+
30+ /// <summary>
31+ /// Tests that given a list of docker projects from the database we can match it against the actively running
32+ /// projects on the server.
33+ /// </summary>
34+ [ Test ]
35+ public async Task DatabaseMatchesCommandOutputSuccessfully ( ) {
36+ // Create three entries in the database for what we allow people to see. All of these should be in the output.
37+ _db . DockerDeployments . AddRange (
38+ new DockerDeployments {
39+ Id = 1 , DisplayName = "Good" , IsDockerComposeProject = true , Name = "Good" , Notes = "Should be in output"
40+ } ,
41+ new DockerDeployments {
42+ Id = 2 , DisplayName = "Good without matching name" , IsDockerComposeProject = true , Name = "NonMatchingName" ,
43+ Notes = "Should be in output"
44+ } ,
45+ new DockerDeployments {
46+ Id = 3 , DisplayName = "Good non-compose" , IsDockerComposeProject = false , Name = "Stuff" ,
47+ Notes = "Should be in output"
48+ }
49+ ) ;
50+ await _db . SaveChangesAsync ( ) ;
51+
52+ // Create two entries "in the server" for what is actually running. We should only match on the "good" one. The bad
53+ // one is different enough that it shouldn't match.
54+ var compose = new List < DockerResource > {
55+ new ( ) { Id = 1 , IsOnline = true , Name = "Good" , Notes = "Should be in output's IsOnline field" } ,
56+ new ( ) { Id = 2 , IsOnline = false , Name = "Bad" , Notes = "Should not be in output" }
57+ } ;
58+ _docker . Setup ( d => d . GetDockerComposeProjects ( It . IsAny < CancellationToken > ( ) ) )
59+ . Returns ( ( ) => Task . FromResult ( compose . AsEnumerable ( ) ) ) ;
60+
61+ var containers = new List < DockerResource > {
62+ new ( ) { Id = 3 , IsOnline = true , Name = "doesn't match" , Notes = "Should not be in output" }
63+ } ;
64+ _docker . Setup ( d => d . GetContainers ( It . IsAny < CancellationToken > ( ) ) )
65+ . Returns ( ( ) => Task . FromResult ( containers . AsEnumerable ( ) ) ) ;
66+
67+ // Make the call and ensure it's successful.
68+ var controller = new DockerController ( _db , _docker . Object ) ;
69+ ObjectResult obj = await controller . GetDockerResources ( ) ;
70+ Assert . That ( obj . StatusCode , Is . EqualTo ( 200 ) ) ;
71+
72+ // There should be three results. One that was actively running "Good" and the others weren't actively running.
73+ var deployments = obj . Value as List < DockerResource > ;
74+ Assert . That ( deployments , Is . Not . Null ) ;
75+ Assert . That ( deployments . Count , Is . EqualTo ( 3 ) ) ;
76+ Assert . That ( deployments . FirstOrDefault ( d => d . Name == "Good" ) ? . IsOnline , Is . True ) ;
77+ Assert . That ( deployments . FirstOrDefault ( d => d . Name == "Good without matching name" ) ? . IsOnline , Is . False ) ;
78+ Assert . That ( deployments . FirstOrDefault ( d => d . Name == "Good non-compose" ) ? . IsOnline , Is . False ) ;
79+ }
80+
81+ /// <summary>
82+ /// Tests that turning on/off a compose project calls the correct thing.
83+ /// </summary>
84+ [ Test ]
85+ public async Task OnOffComposeProjectsWork ( ) {
86+ // Create two entries in the database for what we allow people to adjust.
87+ _db . DockerDeployments . AddRange (
88+ new DockerDeployments {
89+ Id = 1 , DisplayName = "Good" , IsDockerComposeProject = true , Name = "Good" , Notes = "Should be in output"
90+ } ,
91+ new DockerDeployments {
92+ Id = 2 , DisplayName = "Bad" , IsDockerComposeProject = true , Name = "Bad" , Notes = "Should not be in output"
93+ }
94+ ) ;
95+ await _db . SaveChangesAsync ( ) ;
96+
97+ // Only a call with "Good" will work.
98+ _docker . Setup ( d =>
99+ d . TurnOnOffDockerCompose ( "Good" , It . IsAny < bool > ( ) , It . IsAny < CancellationToken > ( ) , It . IsAny < string > ( ) ) )
100+ . Returns ( ( ) => Task . FromResult ( true ) ) ;
101+
102+ // Make the call and ensure it's successful.
103+ var controller = new DockerController ( _db , _docker . Object ) ;
104+ ObjectResult obj =
105+ await controller . TurnOnOrOffDockerResources ( 1 , new TurnOnOrOffDockerResourcesRequest { TurnOn = true } ) ;
106+ Assert . That ( obj . StatusCode , Is . EqualTo ( 200 ) ) ;
107+
108+ // Ensure we called the 3rd party API with a value of "Good" to turn on a compose.
109+ bool deployments = ( bool ) obj . Value ;
110+ Assert . That ( deployments , Is . True ) ;
111+ }
112+
113+ /// <summary>
114+ /// Tests that turning on/off a container project calls the correct thing.
115+ /// </summary>
116+ [ Test ]
117+ public async Task OnOffContainerWork ( ) {
118+ // Create two entries in the database for what we allow people to adjust.
119+ _db . DockerDeployments . AddRange (
120+ new DockerDeployments {
121+ Id = 1 , DisplayName = "Good" , IsDockerComposeProject = false , Name = "Good" , Notes = "Should be in output"
122+ } ,
123+ new DockerDeployments {
124+ Id = 2 , DisplayName = "Bad" , IsDockerComposeProject = false , Name = "Bad" , Notes = "Should not be in output"
125+ }
126+ ) ;
127+ await _db . SaveChangesAsync ( ) ;
128+
129+ // Only a call with "Good" will work.
130+ _docker . Setup ( d => d . TurnOnOffDockerContainer ( "Good" , It . IsAny < bool > ( ) , It . IsAny < CancellationToken > ( ) ) )
131+ . Returns ( ( ) => Task . FromResult ( true ) ) ;
132+
133+ // Make the call and ensure it's successful.
134+ var controller = new DockerController ( _db , _docker . Object ) ;
135+ ObjectResult obj =
136+ await controller . TurnOnOrOffDockerResources ( 1 , new TurnOnOrOffDockerResourcesRequest { TurnOn = true } ) ;
137+ Assert . That ( obj . StatusCode , Is . EqualTo ( 200 ) ) ;
138+
139+ // Ensure we called the 3rd party API with a value of "Good" to turn on a container.
140+ bool deployments = ( bool ) obj . Value ;
141+ Assert . That ( deployments , Is . True ) ;
142+ }
143+
144+ /// <summary>
145+ /// Tests providing an invalid id will result in a HTTP bad request.
146+ /// </summary>
147+ [ Test ]
148+ public async Task InvalidIdIsBadRequest ( ) {
149+ // Create two entries in the database for what we allow people to adjust.
150+ _db . DockerDeployments . Add (
151+ new DockerDeployments {
152+ Id = 2 , DisplayName = "Bad" , IsDockerComposeProject = false , Name = "Bad" , Notes = "Should not be in output"
153+ }
154+ ) ;
155+ await _db . SaveChangesAsync ( ) ;
156+
157+ // Only a call with "Good" will get true.
158+ _docker . Setup ( d => d . TurnOnOffDockerContainer ( "Good" , It . IsAny < bool > ( ) , It . IsAny < CancellationToken > ( ) ) )
159+ . Returns ( ( ) => Task . FromResult ( true ) ) ;
160+
161+ // Make the call and ensure it's successful.
162+ var controller = new DockerController ( _db , _docker . Object ) ;
163+ ObjectResult obj =
164+ await controller . TurnOnOrOffDockerResources ( 1 , new TurnOnOrOffDockerResourcesRequest { TurnOn = true } ) ;
165+ Assert . That ( obj . StatusCode , Is . EqualTo ( 400 ) ) ;
166+
167+ // Bad request is returned to user with a generic error message.
168+ Assert . That ( obj . Value , Is . TypeOf < BasicServerFailure > ( ) ) ;
169+ }
170+ }
0 commit comments