コンテナランタイム開発における libcontainer.Container インターフェースのモック作成とトラブルシューティング
コンテナランタイム開発中に遭遇した libcontainer.Container インターフェースのモック作成に関する問題と、その解決方法についてのメモ。
主に runc ライブラリの libcontainer パッケージを使用し、Go言語でテストを行う際に遭遇したエラーや対処法を記載。
libcontainer.Container インターフェースのモック作成
libcontainer.Container は、コンテナを管理するためのインターフェース。
このインターフェースのモックを作成することで、実際のコンテナを操作することなくテストを行うことができる。
しかし、インターフェースに含まれるすべてのメソッドをモックする必要があるため、エラーが発生しやすい。
1. 必要なパッケージのインポート
以下のパッケージを使用してテストを行う。
import (
"github.com/opencontainers/runc/libcontainer"
"github.com/opencontainers/runc/libcontainer/configs"
"github.com/stretchr/testify/mock"
)
2. 基本的なモックの作成
まず、libcontainer.Container インターフェースの基本的なメソッドをモックする。
type MockContainer struct {
mock.Mock
}
func (m *MockContainer) ID() string {
args := m.Called()
return args.String(0)
}
func (m *MockContainer) Run(process *libcontainer.Process) error {
args := m.Called(process)
return args.Error(0)
}
3. 追加が必要なメソッドの発見
開発中にエラーが発生した場合、そのエラーメッセージをもとに、足りないメソッドを特定し、順次追加する。
例えば、以下のエラーが発生した場合、"NotifyMemoryPressure" メソッドが必要であることがわかる。
*MockContainer does not implement libcontainer.Container (missing method NotifyMemoryPressure) [linux]
4. NotifyMemoryPressure メソッドの追加
以下のように、NotifyMemoryPressure メソッドをモックに追加する。
func (m *MockContainer) NotifyMemoryPressure(level libcontainer.PressureLevel) (<-chan struct{}, error) {
args := m.Called(level)
return args.Get(0).(<-chan struct{}), args.Error(1)
}
PressureLevel は libcontainer パッケージに含まれているため、インポートして使用する。
<トラブルシューティング>
エラー例 1: missing method OCIState
⇒libcontainer.Container インターフェースには OCIState メソッドが含まれており、この場合は以下のように OCIState メソッドを追加する。
func (m *MockContainer) OCIState() (*libcontainer.State, error) {
args := m.Called()
return args.Get(0).(*libcontainer.State), args.Error(1)
}
エラー例 2: missing method Restore ⇒同様に、Restore メソッドもインターフェースに含まれているため、以下のように追加する。
func (m *MockContainer) Restore(process *libcontainer.Process) error {
args := m.Called(process)
return args.Error(0)
}