github.com/Lephar/snapd@v0.0.0-20210825215435-c7fba9cef4d2/client/model_test.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2019 Canonical Ltd
     5   *
     6   * This program is free software: you can redistribute it and/or modify
     7   * it under the terms of the GNU General Public License version 3 as
     8   * published by the Free Software Foundation.
     9   *
    10   * This program is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU General Public License
    16   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17   *
    18   */
    19  
    20  package client_test
    21  
    22  import (
    23  	"encoding/json"
    24  	"errors"
    25  	"io/ioutil"
    26  	"net/http"
    27  
    28  	"golang.org/x/xerrors"
    29  	. "gopkg.in/check.v1"
    30  
    31  	"github.com/snapcore/snapd/asserts"
    32  )
    33  
    34  const happyModelAssertionResponse = `type: model
    35  authority-id: mememe
    36  series: 16
    37  brand-id: mememe
    38  model: test-model
    39  architecture: amd64
    40  base: core18
    41  gadget: pc=18
    42  kernel: pc-kernel=18
    43  required-snaps:
    44    - core
    45    - hello-world
    46  timestamp: 2017-07-27T00:00:00.0Z
    47  sign-key-sha3-384: 8B3Wmemeu3H6i4dEV4Q85Q4gIUCHIBCNMHq49e085QeLGHi7v27l3Cqmemer4__t
    48  
    49  AcLBcwQAAQoAHRYhBMbX+t6MbKGH5C3nnLZW7+q0g6ELBQJdTdwTAAoJELZW7+q0g6ELEvgQAI3j
    50  jXTqR6kKOqvw94pArwdMDUaZ++tebASAZgso8ejrW2DQGWSc0Q7SQICIR8bvHxqS1GtupQswOzwS
    51  U8hjDTv7WEchH1jylyTj/1W1GernmitTKycecRlEkSOE+EpuqBFgTtj6PdA1Fj3CiCRi1rLMhgF2
    52  luCOitBLaP+E8P3fuATsLqqDLYzt1VY4Y14MU75hMn+CxAQdnOZTI+NzGMasPsldmOYCPNaN/b3N
    53  6/fDLU47RtNlMJ3K0Tz8kj0bqRbegKlD0RdNbAgo9iZwNmrr5E9WCu9f/0rUor/NIxO77H2ExIll
    54  zhmsZ7E6qlxvAgBmzKgAXrn68gGrBkIb0eXKiCaKy/i2ApvjVZ9HkOzA6Ldd+SwNJv/iA8rdiMsq
    55  p2BfKV5f3ju5b6+WktHxAakJ8iqQmj9Yh7piHjsOAUf1PEJd2s2nqQ+pEEn1F0B23gVCY/Fa9YRQ
    56  iKtWVeL3rBw4dSAaK9rpTMqlNcr+yrdXfTK5YzkCC6RU4yzc5MW0hKeseeSiEDSaRYxvftjFfVNa
    57  ZaVXKg8Lu+cHtCJDeYXEkPIDQzXswdBO1M8Mb9D0mYxQwHxwvsWv1DByB+Otq08EYgPh4kyHo7ag
    58  85yK2e/NQ/fxSwQJMhBF74jM1z9arq6RMiE/KOleFAOraKn2hcROKnEeinABW+sOn6vNuMVv
    59  `
    60  
    61  // note: this serial assertion was generated by adding print statements to the
    62  // test in api_model_test.go that generate a fake serial assertion
    63  const happySerialAssertionResponse = `type: serial
    64  authority-id: my-brand
    65  brand-id: my-brand
    66  model: my-old-model
    67  serial: serialserial
    68  device-key:
    69      AcZrBFaFwYABAvCgEOrrLA6FKcreHxCcOoTgBUZ+IRG7Nb8tzmEAklaQPGpv7skapUjwD1luE2go
    70      mTcoTssVHrfLpBoSDV1aBs44rg3NK40ZKPJP7d2zkds1GxUo1Ea5vfet3SJ4h3aRABEBAAE=
    71  device-key-sha3-384: iqLo9doLzK8De9925UrdUyuvPbBad72OTWVE9YJXqd6nz9dKvwJ_lHP5bVxrl3VO
    72  timestamp: 2019-08-26T16:34:21-05:00
    73  sign-key-sha3-384: anCEGC2NYq7DzDEi6y7OafQCVeVLS90XlLt9PNjrRl9sim5rmRHDDNFNO7ODcWQW
    74  
    75  AcJwBAABCgAGBQJdZFBdAADCLALwR6Sy24wm9PffwbvUhOEXneyY3BnxKC0+NgdHu1gU8go9vEP1
    76  i+Flh5uoS70+MBIO+nmF8T+9JWIx2QWFDDxvcuFosnIhvUajCEQohauys5FMz/H/WvB0vrbTBpvK
    77  eg==`
    78  
    79  const noModelAssertionYetResponse = `
    80  {
    81  	"type": "error",
    82  	"status-code": 404,
    83  	"status": "Not Found",
    84  	"result": {
    85  	  "message": "no model assertion yet",
    86  	  "kind": "assertion-not-found",
    87  	  "value": "model"
    88  	}
    89  }`
    90  
    91  const noSerialAssertionYetResponse = `
    92  {
    93  	"type": "error",
    94  	"status-code": 404,
    95  	"status": "Not Found",
    96  	"result": {
    97  	  "message": "no serial assertion yet",
    98  	  "kind": "assertion-not-found",
    99  	  "value": "serial"
   100  	}
   101  }`
   102  
   103  func (cs *clientSuite) TestClientRemodelEndpoint(c *C) {
   104  	cs.cli.Remodel([]byte(`{"new-model": "some-model"}`))
   105  	c.Check(cs.req.Method, Equals, "POST")
   106  	c.Check(cs.req.URL.Path, Equals, "/v2/model")
   107  }
   108  
   109  func (cs *clientSuite) TestClientRemodel(c *C) {
   110  	cs.status = 202
   111  	cs.rsp = `{
   112  		"type": "async",
   113  		"status-code": 202,
   114                  "result": {},
   115  		"change": "d728"
   116  	}`
   117  	remodelJsonData := []byte(`{"new-model": "some-model"}`)
   118  	id, err := cs.cli.Remodel(remodelJsonData)
   119  	c.Assert(err, IsNil)
   120  	c.Check(id, Equals, "d728")
   121  	c.Assert(cs.req.Header.Get("Content-Type"), Equals, "application/json")
   122  
   123  	body, err := ioutil.ReadAll(cs.req.Body)
   124  	c.Assert(err, IsNil)
   125  	jsonBody := make(map[string]string)
   126  	err = json.Unmarshal(body, &jsonBody)
   127  	c.Assert(err, IsNil)
   128  	c.Check(jsonBody, HasLen, 1)
   129  	c.Check(jsonBody["new-model"], Equals, string(remodelJsonData))
   130  }
   131  
   132  func (cs *clientSuite) TestClientGetModelHappy(c *C) {
   133  	cs.status = 200
   134  	cs.rsp = happyModelAssertionResponse
   135  	modelAssertion, err := cs.cli.CurrentModelAssertion()
   136  	c.Assert(err, IsNil)
   137  	expectedAssert, err := asserts.Decode([]byte(happyModelAssertionResponse))
   138  	c.Assert(err, IsNil)
   139  	c.Assert(modelAssertion, DeepEquals, expectedAssert)
   140  }
   141  
   142  func (cs *clientSuite) TestClientGetModelNoModel(c *C) {
   143  	cs.status = 404
   144  	cs.rsp = noModelAssertionYetResponse
   145  	cs.header = http.Header{}
   146  	cs.header.Add("Content-Type", "application/json")
   147  	_, err := cs.cli.CurrentModelAssertion()
   148  	c.Assert(err, ErrorMatches, "no model assertion yet")
   149  }
   150  
   151  func (cs *clientSuite) TestClientGetModelNoSerial(c *C) {
   152  	cs.status = 404
   153  	cs.rsp = noSerialAssertionYetResponse
   154  	cs.header = http.Header{}
   155  	cs.header.Add("Content-Type", "application/json")
   156  	_, err := cs.cli.CurrentSerialAssertion()
   157  	c.Assert(err, ErrorMatches, "no serial assertion yet")
   158  }
   159  
   160  func (cs *clientSuite) TestClientGetSerialHappy(c *C) {
   161  	cs.status = 200
   162  	cs.rsp = happySerialAssertionResponse
   163  	serialAssertion, err := cs.cli.CurrentSerialAssertion()
   164  	c.Assert(err, IsNil)
   165  	expectedAssert, err := asserts.Decode([]byte(happySerialAssertionResponse))
   166  	c.Assert(err, IsNil)
   167  	c.Assert(serialAssertion, DeepEquals, expectedAssert)
   168  }
   169  
   170  func (cs *clientSuite) TestClientCurrentModelAssertionErrIsWrapped(c *C) {
   171  	cs.err = errors.New("boom")
   172  	_, err := cs.cli.CurrentModelAssertion()
   173  	var e xerrors.Wrapper
   174  	c.Assert(err, Implements, &e)
   175  }